I understand the benefits of events using delegate types with signature delegate void delegate_name(object sender, EventArgs e)
a) But besides the fact that it may save us some typing, are there any other reasons why we should use already defined delegate types EventHandler/EventHandler<T>
instead of declaring our own delegate types with signature delegate void delegate_name(object sender, EventArgs e)
?
b) Two other reason I can think of for using the predefined delegate types EventArgs/EventArgs<T>
are:
people consuming particular event ( say
event EventHandler my_event
) will immediately know how to use that event?perhaps some popular third party methods accept as parameters
EventHandler/ EventHandler<T>
delegate types, and thus if there’s 开发者_StackOverflow中文版any chance that our code may use those third party methods, we should use predefined delegatesEventHandler/Eventhandler<T>
?
thank you
To me, the question is a little strange. What would be the benefit of doing this otherwise (defining delegate types that exactly match EventHandler<TEventArgs>
for some TEventArgs
)?
That said, there is at least one benefit I can think of to doing it the "normal" way: certain APIs already expect to deal with EventHandler<TEventArgs>
delegates; for example, Rx Extensions includes a method that looks like this:
Observable.FromEvent<TEventArgs>(
Action<EventHandler<TEventArgs>> addHandler,
Action<EventHandler<TEventArgs>> removeHandler
);
If you defined your own delegate, using methods like this -- which expect EventHandler<TEventArgs>
delegates -- would become more complicated than necessary for no added benefit (that I can see, anyway).
You forgot an important one:
- the lunatic that will maintain your code some day will find out where you live and hurt you.
You've answered your own question:
- Syntactical Sugar (less to write) to maintain the convention
- Interoperability (using the
EventHandler
type let's you easily integrate events from other libraries
In short; there's no good reason not to use it unless you're forced to (which typically is the result of people not being aware of it, or not understanding it).
From Pro C# 2008 and the .NET 3.5 Platform:
When the compiler processes the event keyword, you are automatically provided with registration and unregistration methods* as well as any necessary member variables** for your delegate types. ...To be sure, the event keyword is little more than syntactic sugar in that it simply saves you some typing time.
* This includes overloading the handy +=
and -=
operators.
** ...which are already marked private
so they can't end-run.
When you use the generic EventHandler delegate, you don't even have to write out your custom delegate type at all.
I'm going to rock the boat here and propose something entirely heretical. I used to be firmly in the EventArgs
camp because I clung to the "MS recommends this and it's always been done this way" mentality, but over time I came to hate EventArgs
. Why?
- It promotes a .NET-1.0ish style of coding which relies upon weak-typing/type casting and makes me feel unclean.
- It forces your class which implements the event to pollute the heap with new
EventArg
instances every time it fires, which also makes me uneasy. Why not have my events give subscribers exactly what they need instead of wrapping it up in an extra class that does nothing for me. - The signatures of your callback methods which subscribe to the event look like garbage and have very little semantic detail - e.g.
object sender
- WHAT is sender?!?!
What I do now is declare my own event handler delegates, which I store neatly in their own "Delegates" folder in my solution as well as their own namespace. So my delegate may reside in its own file like this:
namespace MyAPI.Data.Delegates
{
public delegate void DataEventHandler<TData>(DataFeed<TData> sender, TData data);
}
The event declaration now looks like this:
public event DataEventHandler<TData> DataReady = delegate { };
Benefits to this approach:
- Method signatures have more semantic detail. You know WHO is sending WHAT.
- Strong-typing is preserved. No more casting
object sender
to what you think it should be. - You don't have to
new()
up objects and pollute the heap, which can be problematic if your event fires frequently. Just pass your subscribers exactly what they need, whether it be an object reference or a value type. - By using the
___EventHandler
naming convention for your delegates, you are still promoting a uniform style for your code which makes it easy for users of your API to know what your intent is.
The only "drawback" is that it makes it hard for users of your code to wire up your event to existing methods which have the object sender, EventArgs e
signature. However, this point is moot because if your event delivers any extra data (e.g. you created your own EventArgs
subclass) then they'll have to change the method signature anyway (or cast to your subclass type). Either way, that's still nasty.
That's why I like my way.
精彩评论