Three different ways to raise events in C#

The Event model in C# finds its roots in the event programming model that is popular in asynchronous programming. The basic foundation behind this programming model is the idea of "publisher and subscribers." In this model, you have publishers who will do some logic and publish an "event." Publishers will then send out their event only to subscribers who have subscribed to receive the specific event.

In C#, any object can publish a set of events to which other applications can subscribe. When the publishing class raises an event, all the subscribed applications are notified. The following figure shows this mechanism.

From Delegates and Events in C# / .NET

Using events is C# is easy – all that is needed is to add a handler method and attach it using ‘+=’. It is a common practice in a class that declares the event to check if anyone is listening on it using a simple If block:

if(eventWithIfBlock != null) 
{ 
eventWithIfBlock(this, EventArgs.Empty); 
}


It isn’t very elegant but it works and could be refactored to a function in case the event is needed to be thrown from multiple places in the code.



But there are more elegant ways to handle the problem of event not having any listeners.



Using empty delegate (.NET 2.0)



One trick I learnt (but didn’t invent) is using an empty anonymous delegate as a “default listener” so that the event would never be “null”:



public EventHandler eventWithEmptyDelegate = delegate{};


It is a simple and elegant solution that makes sure that our code would never throw a NullReferenceException due to no one listening on the event.



Using Extension Methods (.NET 3.5)



I found this cool trick in Michel Grootjans’s blog in Elegant way to raise an event.



It is a simple improvement of the basic if block by adding an extension method Raise() the event type class:



public static class EventHandlerExtension
{
public static void Raise(this ClassWithEvents.EventHandler eventToThrow, object sender, EventArgs args)
{
if(eventToThrow != null)
{
eventToThrow(sender, EventArgs.Empty);
}
}
}


And then throwing the event is very simple and elegant:



public void ThrowEventUsingExtensionMethod()
{
eventWithExtensionMethod.Raise(this, EventArgs.Empty);
}


Performance considerations



All is nice and well but what if many events throws happens during the execution of the code, is there a preferred method performance-wise?



I’ve wrote simple program using Stopwatch to check what is the performance cost of using each of those methods.



In the test calls each event 1M times and then connects a listener method and calls then event one million times more.



The results are:



image



Let me explain the results – it doesn’t really matters! whatever method you choose the price of calling each of the method 1M times is less then a 0.2 of a second.



Although a simple comparison shows that using an empty delegate (method #2) takes a bit more time then the other two methods but I doubt it would effect the overall performance of an application.

Labels: ,