Thursday, April 14, 2016

Events Using Delegates in C#

In today's blog post, I will be discussing a simple example of events in C#. We will be using delegates in this post to explain how events work.

Events

An event is a way to notify clients of the occurrence of something of interest to the clients. Events follow a publish-subscribe model. Any client that wants to listen to an event can subscribe to it and when the event occurs the client is notified.

Events in C#

Events Using Delegates

I discussed delegates some time back here. Let's look at an example of how we can implement events using delegates. Here we have an ArrayList which invokes an event called Changed whenever the contents of the list change.

public delegate void ChangedEventHandler(object sender, EventArgs e);

public class ListWithChangedEvent : ArrayList
{
    public event ChangedEventHandler Changed;
    protected virtual void OnChanged(EventArgs e)
    {
            if (Changed != null)
                Changed(this, e);
     }

    public override int Add(object value)
    {
        int i = base.Add(value);
         OnChanged(EventArgs.Empty);
        return i;
    }

    public override void Clear()
    {
        base.Clear();
        OnChanged(EventArgs.Empty);
    }

    public override object this[int index]
    {
        set
        {
            base[index] = value;
            OnChanged(EventArgs.Empty);
        }
    }
}

The delegate is declared first which decides the method signature which can be assigned to the delegate. Next, we declare the special type of list.
Inside the ListWithChangedEvent, first the event is declared. Next, the event is invoked. Inside the method, we check if Changed is not null to avoid null exception. That's a standard practice to avoid null exception while invoking events. Other than that, standard methods are exposed to interact with the List and change it's contents. Inside each of the method, note that the OnChanged event is fired.

Suppose, we want to output a line whenever the event is fired. So we simply have a method like this:

private static void ListChanged(object sender, EventArgs e)
{
      Console.WriteLine("Event Occurred. List Changed.");
}

And then in the Main method we create the list, add the handler to the Changed event. Then, we call the Add and Clear method on the list.

static void Main(string[] args)
{
       ListWithChangedEvent list = new ListWithChangedEvent();
       list.Changed += new ChangedEventHandler(ListChanged);
       list.Add("item 1");
       list.Clear();
       Console.ReadLine();
}

As a result, the event is fired twice, once each for Add and Clear methods.
So we get the output like this:

Event Occurred. List Changed.
Event Occurred. List Changed.


Conclusion

So we saw how to use events using delegates in this post. Events help us decouple our code so the invoking code doesn't need to know what happens when the event is occurred. The calling code itself (or any other part of the system) can decide what to do when the event is fired.  Next week, I will be discussing how to use events without using delegates explicitly.

For future updates to my weekly blog, please subscribe to my blog via the "Subscribe To Weekly Post" feature at the right and follow me on Twitter. Until then Happy Coding :)


Reference: MSDN

2 comments:

  1. One important issue with events is that you should always make a defensive copy of the delegate before you check for null. A worker thread could unsubscribe from Changed in between you checking Changed != null and invoking Changed(this, e) and you cause a NullReferenceException.

    The standard has been to do this: var handler = Changed; if (handler != null) handler(this, e);

    But now with C# 6, the standard is both safer and shorter: Changed?.Invoke(this, e);

    ReplyDelete
    Replies
    1. Hi Joseph, creating a copy sounds like a good idea. Thanks for pointing that out. Also, the C# 6 syntax looks pretty cool too. Thanks again :)

      Delete