I noticed this while using the Ping class. I originally followed C#'s documentation when implementing the PingCompleted callback method:
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
However, when I was adding a new method to the Timer's Elapsed event, I noticed that I wasn't passing a new TimerElapsedEventHandler. Instead, I was just passing the function name as is:
customTimer.Elapsed += CustomTimerElapsedCallback;
I tested this out with the PingCompleted event and it still works:
pingSender.PingCompleted += PingCompletedCallback;
I couldn't find any source that specifically explains why this is. Can anyone explain why this is allowed and what the EventHandler calls does?
This is handled by the C# compiler for you. It was a feature added in C# 2.0 (see section on "How to: Declare, Instantiate, and Use a Delegate").
The C# Language Spec, Section 6.6, states:
An implicit conversion (§6.1) exists from a method group (§7.1) to a compatible delegate type. Given a delegate type D and an expression E that is classified as a method group, an implicit conversion exists from E to D if E contains at least one method that is applicable in its normal form (§7.5.3.1) to an argument list constructed by use of the parameter types and modifiers of D
Basically, you can just use the name of a method in your code (which is a "method group", in your case, CustomTimerElapsedCallback
or PingCompletedCallback
), and the compiler will see that a delegate type is required, and put in the logic to do the conversion for you.
The resulting generated IL for pingSender.PingCompleted += PingCompletedCallback;
and pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
are exactly the same as a result.