Short Tutorial on Delegates and Events

This post is a short tutorial on delegates and events. First, I will describe what delegates and events are, and what they can be used for. Then, I will give a simple example code using a delegate and an event. I will finish by criticising my own example with comments on what and how can be improved.

Let’s start!

In C#, a delegate is a sealed class that derives from System.MulticastDelegate, which is an abstract class that provides some useful functionality. This useful functionality includes binding a delegate to a method or a list of methods, as well as obtaining the list of methods a delegate can invoke once it was bound to them; removing methods from the delegate list, and also returning basic information about the methods a delegate can invoke. When you declare a delegate, the compiler creates the mentioned sealed class for you. It also creates a constructor and three methods for invoking the bound method/s synchronously or asynchronously.  An event is also a delegate, a special one, and it is always declared as an instance of an existing delegate type with a keyword event. I know that this sounds confusing, so, let me show you what I mean:

 

public delegate void EventHandler();    //delegate
public event EventHandler EnteredEight; //event on a delegate


In the above, I declare a delegate EventHandler and an event instance of type EventHandler, called  EnteredEight . The two are now bound together.

Ok, so what can we do with this delegate and event? We can bind a method to the EventHandler and define a process that triggers the EnteredEight event. If you are thinking that my variable names are a bit crazy, let me say that I am doing this to customize the explanation to the example below, where I define a process that fires EnteredEight event when a user enters number ‘8’ on a keyboard (note: for a more useful example of using delegates, check out this post on numerical integration).

 

using System.Collections;
namespace DelegatesAndEvents
{
   public class ListWithEightEvent : ArrayList
   {
      public delegate void EventHandler();    //delegate type
      public event EventHandler EnteredEight; //event on a delegate
      // invoke event after an addition of an 8
      //process that fires the event
      public override int Add(object value)
      {
         int i = base.Add(value);
         if (EnteredEight != null && value.ToString()=="8")
             EnteredEight(); //envoking the event
         return i;
      }
    }

    class Test
    {
       public static void Main()
       {
         ListWithEightEvent list = new ListWithEightEvent(); //class instantiation
         //registering event with the delegate bound to AddedEight method
         list.EnteredEight += new ListWithEightEvent.EventHandler(AddedEight);
         string input;
         Console.WriteLine("Keep entering numbers. Enter 'x' to stop.");
         do{
             input = Console.ReadLine();
             list.Add(input);
         }while(input!="x");
        }
        
        // This will be called whenever the list receives an 8
        public static void AddedEight()
        {
           Console.WriteLine("You have entered an 8!");
        }
     }
}


An example output of this program is shown below:

DelegateandEventExample

 

I have to give credit to the MSDN tutorial for the above code which I stripped off all the extra bits and changed a little to expose the basic delegate-event functionality. Let’s step through the code to work out what is happening. First, I declare a public delegate EventHandler and an event on this delegate, called EnteredEight. I then override the Add method to not only add the user-entered value to the ArrayList, but also to invoke the EnteredEight event if a user presses ‘8’. This is achieved through the AddedEight method that simply writes a line to the console to acknowledge that a number ‘8’ has been entered. In the Main method I instantiate my class and register my event with the delegate, which is bound to the AddedEight method. C# provides ‘+=’ operator to allow an easy way of registering events with delegates bound to some method/s. It is useful to know that the compiler expands this operator to event’s internally defined add_XXX method, which becomes

add_EnteredEight(class DelegatesAndEvents.ListWithEightEvent/EventHandler) in my example.

This tutorial’s example is trivial, and one can do without delegates and events to achieve the same functionality. Also, this example omits several important points about delegates and events. For example, the signature of the delegate must match the signature of the method it is bound to (here, the return type is included in the ‘signature’ meaning). In my example, the signature is “accepts no parameters and returns no parameters”. If I were to change AddedEight to receive or return a value, I would also need to change the delegate declaration. Also, we could have achieved the same functionality with delegates but no events. This is because EventHandler is just a delegate type. Instead of instantiating an event type delegate, I could have directly created non-event EventHandler delegate instance and bound it to a method. The beauty of using events is that the ListWithEightEvent class does not need to have variable of type delegate EventHandler, which would need to be private to protect its integrity. When using events, the compiler creates the delegate member variable for us and always declares it as private.

Can you think of what would happen if I registered Main() with the delegate? A truly bizarre thing happens and I urge you to try it out and examine the program’s stack!