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