Assigning to C# events

When raising an event in C#, you first have to make sure it isn’t null, because it will be null if there are no subscribers.

public event EventHandler Click;
public void RaiseClick()
{
    // throws NullReferenceException if no subscribers

    //    Click(this, EventArgs.Empty);

    // could throw NullReferenceException if unsubscribed on another thread

    //    if (Click != null)

    //        Click(this, EventArgs.Empty);

    // never throws NullReferenceException

    EventHandler handler = Click;
    if (handler != null)
        handler(this, EventArgs.Empty);
}

A few weeks ago, Andy Clymer demonstrated a fun way to avoid that boilerplate null-checking code by simply adding a do-nothing event handler.

public event EventHandler Click = delegate { };
public void RaiseClick()
{
    // never throws NullReferenceException

    Click(this, EventArgs.Empty);
}

Call me crazy, but somehow I didn’t realize that I could assign to events! In fact, you can assign to events anywhere within the declaring class; you’ll note that I do so twice in my previous post.

In the constructor, I use a similar pattern to always call a virtual method as the first event handler:

Disposing = delegate { OnDisposing(); };

And in the Dispose method, I assign the event to null to unsubscribe all of my subscribers.

Disposing = null;

I should mention that I’m not claiming that any of these patterns make events “thread safe” by any stretch; they only help to avoid throwing a NullReferenceException. In fact, I hope to talk more about the thread safety of events in a future post.

(You’ll note that the name of my event-raising method starts with “Raise” rather than “On” – I agree with Sebastien Lambla that raising events from OnXxx methods is an anti-pattern.)

Posted by Ed Ball on March 07, 2008