Create empty C# event handlers automatically
It is not possible to fire an event in C# that has no handlers attached to it. So before each call it is necessary to check if the event is null.
if ( MyEvent != null ) {
MyEvent( param1, param2 );
}
I would like to keep my code as clean as possible and get rid of those null checks. I don't think it will affect performance very much, at least not in my case.
MyEvent( param1, param2 );
Right now I solve this by adding an empty inline handler to each event manually. This is error prone, since I need to remember to do that etc.
void Initialize() {
MyEvent += new MyEvent( (p1,p2) => { } );
}
Is there a way to generate empty handlers for all events of a given class automatically using reflection and some CLR magic?
I saw this on another post and have shamelessly stolen it and used it in much of my code ever since:
public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!
//Let you do this:
public void DoSomething() {
Click(this, "foo");
}
//Instead of this:
public void DoSomething() {
if (Click != null) // Unnecessary!
Click(this, "foo");
}
* If anyone knows the origin of this technique, please post it in the comments. I really do believe in the source getting due credit.
(Edit: I got it from this post Hidden Features of C#?)
The notation:
if ( MyEvent != null ) {
MyEvent( param1, param2 );
}
is not thread safe. You should do it this way:
EventHandler handler = this.MyEvent;
if ( null != handler ) { handler( param1, param2 ); }
I understand, that this is a bother, so you can do helper method:
static void RaiseEvent( EventHandler handler, object sender, EventArgs e ) {
if ( null != handler ) { handler( sender, e ); }
}
and then call:
RaiseEvent( MyEvent, param1, param2 );
If you are using C# 3.0, you can declare helper method as extension method:
static void Raise( this EventHandler handler, object sender, EventArgs e ) {
if ( null != handler ) { handler( sender, e ); }
}
and then call:
MyEvent.Raise( param1, param2 );
Also you can create next extension/helper methods for other event handlers. For example:
static void Raise<TEventArgs>( this EventHandler<TEventArgs> handler,
object sender, TEventArgs e ) where TEventArgs : EventArgs
{
if ( null != handler ) { handler( sender, e ); }
}
In C# 6.0 there's no need to go to any of these lengths to do the null check, thanks to the conditional null operator ?.
The docs explain that calling MyEvent?.Invoke(...)
copies the event to a temporary variable, performs the null check, and if not null, calls Invoke
on the temporary copy. This isn't necessarily thread-safe in every sense, as someone could have added a new event after the copy to the temporary variable, which wouldn't be called. It does guarantee you won't call Invoke
on null though.
In short:
public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click;
public void DoSomething() {
Click?.Invoke(this, "foo");
}