Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
337 views
in Technique[技术] by (71.8m points)

.net - C#: event with explicity add/remove != typical event?

I have declared a generic event handler

public delegate void EventHandler();

to which I have added the extension method 'RaiseEvent':

public static void RaiseEvent(this EventHandler self)        {
   if (self != null) self.Invoke();
}

When I define the event using the typical syntax

public event EventHandler TypicalEvent;

then I can call use the extension method without problems:

TypicalEvent.RaiseEvent();

But when I define the event with explicit add/remove syntax

private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent {
   add { _explicitEvent += value; } 
   remove { _explicitEvent -= value; }
}

then the extension method does not exist on the event defined with explicit add/remove syntax:

ExplicitEvent.RaiseEvent(); //RaiseEvent() does not exist on the event for some reason

And when I hover over to event to see the reason it says:

The event 'ExplicitEvent' can only appear on the left hand side of += or -=

Why should an event defined using the typical syntax be different from an event defined using the explicit add/remove syntax and why extension methods do not work on the latter?

EDIT: I found I can work around it by using the private event handler directly:

_explicitEvent.RaiseEvent();

But I still don't understand why I cannot use the event directly like the event defined using the typical syntax. Maybe someone can enlighten me.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you create a "field-like" event, like this:

public event EventHandler Foo;

the compiler generates a field and an event. Within the source code of the class which declares the event, any time you refer to Foo the compiler understand that you're referring to the field. However, the field is private, so any time you refer to Foo from other classes, it refers to the event (and therefore the add/remove code).

If you declare your own explicit add/remove code, you don't get an auto-generated field. So, you've only got an event, and you can't raise an event directly in C# - you can only invoke a delegate instance. An event isn't a delegate instance, it's just an add/remove pair.

Now, your code contained this:

public EventHandler TypicalEvent;

This is slightly different still - it wasn't declaring an event at all - it was declaring a public field of the delegate type EventHandler. Anyone can invoke that, because the value is just a delegate instance. It's important to understand the difference between a field and an event. You should never write this kind of code, just as I'm sure you don't normally have public fields of other types such as string and int. Unfortunately it's an easy typo to make, and a relatively hard one to stop. You'd only spot it by noticing that the compiler was allowing you to assign or use the value from another class.

See my article on events and delegates for more information.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...