« Thread-safe disposable objects | Main | EmptyIfNull »

March 7, 2008

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 at March 7, 2008 8:49 AM

Trackback Pings

TrackBack URL for this entry:
http://blog.logos.com/mt-cgi/mt-tb.cgi/190

Listed below are links to weblogs that reference Assigning to C# events:

» Book Review: Programming .NET Components, 2nd Edition from Ed at Work
[Read More]

Tracked on March 28, 2008 8:49 AM

Comments

That's a pretty interesting trick. It never occurred to me to attempt an assignment after an event declaration.

Posted by: Dustin Campbell at March 7, 2008 9:24 AM

You might be interested in the EventsHelper class mentioned in the book "Programming .NET Components" by Juval Löwy. Searching for "EventsHelper" will find an implementation of it. Basically, it does a lot of safety checks like checking for null delegates, continues processing if a handler throws an exception, ensures UI event handlers run on the UI thread if they need to as well as much more.

The only modification I'd suggest is renaming "Fire" to "Raise" on the methods. It's a very helpful class.

Posted by: Jeff Moser at March 7, 2008 9:48 AM

Thanks for the tip, Jeff. I haven't read Löwy's second edition yet, but I'll be sure to check it out.

Posted by: Ed Ball at March 10, 2008 10:05 AM

Thanks for the link, glad someone agreed with me on the OnXxx debacle :)

Great blog, added!

Posted by: Sebastien Lambla at April 5, 2008 10:11 AM

Post a comment




(you may use HTML tags for style)