Thursday, November 15, 2012

Raise events properly


Don't raise an event just by "calling" it. You'll get NullReferenceException when there are no subscribers. Surprise!
Instead, you should check for null before trying to invoke the delegate:
if ( MyEvent != null ) MyEvent( this, EventArgs.Empty );
But that's also not good enough: in a multithreaded application, the last subscriber might unsubscribe from the event between the null check and the calling point, rendering the variable null and causing same old NullReferenceException.

To safeguard from that, one should cache the value in a local variable first:

var ev = MyEvent;
if ( ev != null ) ev( ... );

I have also found it useful to have an extension method for this case:
public static void Raise ( this EventHandler h, object sender )
{
    if ( h != null) h( sender, EventArgs.Empty );
}
And then:
MyEvent.Raise ( this );

And also add the generic case:
public static void Raise<T>( this EventHandler<T> h, object sender, T args )
   where T : EventArgs
{
    if ( h != null) h( sender, args );
}

No comments:

Post a Comment