开发者

What controls where an event can be called?

开发者 https://www.devze.com 2023-01-28 01:18 出处:网络
Say I have a class like this: public class FauxIdentityForm { public Guid FormID { get; set; } public event EventHandler Closed;

Say I have a class like this:

public class FauxIdentityForm
{
    public Guid FormID { get; set; }
    public event EventHandler Closed;
    public void TheObjectWasClosed(EventArgs e)
    {
        Closed(this, e);
    }
}

It is fine for me to call the Closed Event inside the TheObjectWasClosed method. But if, in a different class (even in the same file), 开发者_如何学PythonI have a method like this:

public void CallTheEvent()
{
    FauxIdentityForm _formIdentity = new FauxIdentityForm {FormID = Guid.NewGuid()};

    _formIdentity.Closed(_formIdentity, null);  // <-- Does not compile!
}

The call to Closed is shot down by the compiler (it wants me to only use += and -=).

So, is actually calling the event only allowed inside the class? Is that the limitation?

If so, is there anyway around it? And if not, why did the creators of C# do this? (It makes working with events very hard sometimes. I imagine there is a good reason and it is probably saving me from myself, but I would like to know it.)


It's complicated :)

What you're using is called a field-like event. When you declare one of those in your class, you're creating a field and an event. When you "call the event" you're actually invoking the delegate referred to by the field. As it's a private field, you have access to it within the class (and any nested types), but not outside.

Events themselves in C# only support add and remove operations. From the outside, callers can only subscribe to an event and unsubscribe from it. They can't raise it, or find out anything about who's subscribed. Of course, the class can provide a method which will raise the event, but the other class can't access the backing field for the event

I've written this up in more detail in an article about events and delegates.


In fact, Closed(this, e); is nothing but calling invoke on a private delegate. This is why only the class can call it.

C# hides all the complexity from you and it creates a private delegate of type event for you (you can use ILDASM to see all this).

This is private so it is not even protected. This is why it is recommended to use a protected method to raise the event so the subclasses could have access to the event.


So, is actually calling the event only allowed inside the class? Is that the limitation?

Yes

If so, is there anyway around it?

Only with the consent (help) from the FauxIdentityForm class. It could have a public OnClosed() method.
An Event is a lot like a property, one of its main purposes is encapsulation and that is what you ran into.

0

精彩评论

暂无评论...
验证码 换一张
取 消