Event and Delegate in C#

Delegate is similar to a function pointer in C/C++ but it is type safe in C#.

A delegate is an object that can refer to a method. It means that it can hold a reference to a method. The method can be called through this reference or we can say that a delegate can invoke the method to which it refers. The same delegate can be used to call different methods during the runtime of a program by simply changing the method to which the delegate refers. The main advantage of a delegate is that it invokes the method at run time rather than compile time. A delegate type is declared using the keyword delegate. Delegate types are derived from the Delegate class.

The prototype of a delegate declaration is given below:

delegate ret-type name(parameter-list);

Important Note: A delegate can call only those methods that have same signature and return type as delegate.

Example:
delegate int MathsOperation(int a, int b);

This delegate can only call those methods that have integer return type and take two arguments as integer.

Example

using System;
namespace ConsoleApplication1
{
    // Declaration of delegate
    // This delegate can call only those methods which has
    // integer return type and takes two integer type parameter.
    delegate int MathsOperation(int a, int b);
    public class DelegateDemo
    {        
        public int Addition(int x, int y)
        {
            return x + y;
        }
        public int Subtraction(int x, int y)
        {
            return x - y;
        }           
    }
    class Program
    {
        static void Main(string[] args)
        {
            DelegateDemo obj = new DelegateDemo();
            // Provides the function reference to the delegate.
            MathsOperation delgateObj = new MathsOperation(obj.Addition);
            // Delegate call
            int resAdd = delgateObj(10, 20);
            Console.WriteLine("Addition    =: "+resAdd);
            delgateObj = new MathsOperation(obj.Subtraction);
            Console.WriteLine("Subtraction =: " + delgateObj(100, 50));
            Console.ReadLine();
        }
    }
}


The above program declares a delegate as follows:

delegate int MathsOperation(int a, int b);

It takes two integer parameter and returns an integer type. In class DelegateDemo two instance methods are declare, whose parameter type and return type is same as delegate prototype. Therefore delegate object can refer these methods.
In Main method create the object of delegate as:

MathsOperation delgateObj = new MathsOperation(obj.Addition);

It is important to note that, we have passed the name of function without parameter.
Next, delgateObj is assigned a reference to Subtraction ( ) method and then delgateObj is called again. Therefore, Subtraction ( ) method is invoked.

Multicast delegate

Delegate supports multicasting. It means that multicast delegate enables you to create chain of methods that will be automatically called when a delegate is invoked.

Performing chaining of function is very easy.

Use the + or += operator to add methods to the chain and for removing a method, use – or – =.

So += operator is used to register a function and -= will remove the registration from the delegate.
In general a multicast delegate return type is void.

Example

using System;
namespace ConsoleApplication1
{
    // Declaration of delegate
    // This delegate can call only those methods which has
    // void return type and takes two integer type parameter.
    delegate void MathsOperation(int a, int b);
    public class DelegateDemo
    {        
        public void Addition(int x, int y)
        {
            Console.WriteLine("Addition of {0} and {1} is =: {2}",x,y,(x + y));
        }
        public void Subtraction(int x, int y)
        {
            Console.WriteLine("Subtraction of {0} and {1} is =: {2}", x, y, (x - y));
        }
           
    }
    class Program
    {
        static void Main(string[] args)
        {
            DelegateDemo obj = new DelegateDemo();
            // Provides the function reference to the delegate.
            MathsOperation delgateObj = new MathsOperation(obj.Addition);
            // Delegate call, prints only addition
             delgateObj(10, 20);
             Console.WriteLine();
           // Delegate call, prints  addition and subtraction.
           // You can use any of the following method.
           // delgateObj += new MathsOperation(obj.Subtraction);  or
            delgateObj +=obj.Subtraction;
            delgateObj(100, 50);
            Console.ReadLine();
        }
    }
}


Output:

Addition of 10 and 20 is =: 30
Addition of 100 and 50 is    =: 150
Subtraction of 100 and 50 is =: 50

Anonymous Methods

In the above section we have learnt that, how to use delegate.
  • Declare a delegate.
  • Create methods with implementation. Methods prototype should be same as delegate.
  • Create instance of delegate and refer to method.
In the above process methods are refer by delegates and not called by object of the class or class name. There are lots of unnecessary code is there. Therefore a couple of steps can be removed, with the help of anonymous method.

An anonymous method is a method without any name. That’s why it is called as anonymous method.  Anonymous methods can be used in the place where there is a use of a delegate. It is created using the delegate keyword.

Example

using System;
namespace ConsoleApplication1
{    
    delegate void Factorial(int a);    
    class Program
    {
        static void Main(string[] args)
        {
            Factorial delgateObj = delegate(int n)
            {
                int fact = 1;
               for(int i=1; i<=n; i++)
               {
                   fact = fact * i;
               }
               Console.WriteLine ("Factorial of {0} is =: {1}", n, fact);
            };
            Console.WriteLine ("Enter the number to find the factorial");
            int no =Convert.ToInt32( Console.ReadLine());
            delgateObj(no);
            Console.ReadLine();
        }
    }
}


If you don’t want to pass any parameter to anonymous function, then declare the method as

Factorial delgateObj = delegate
{
     // Your code ……….
}


Return a Value from an Anonymous Method

An anonymous method can return a value by use of the return statement.

using System;
namespace ConsoleApplication1
{    
    delegate int Add(int a, int b);    
    class Program
    {
        static void Main(string[] args)
        {
            Add delgateObj = delegate(int x,int y)
            {                
               return x+y;              
            };
            Console.WriteLine("Enter two number for addition");
            int a=Convert.ToInt32( Console.ReadLine());
            int b = Convert.ToInt32(Console.ReadLine());
            int sum = delgateObj(a, b);
            Console.WriteLine("Addition of {0} and {1} is =: {2}",a,b,sum);
            Console.ReadLine();
        }
    }
}


In the above example, the summation of two integer number is returned by the code block that is associated with the Add delegate instance. Please keep in mind that the return statement is used in an anonymous method in just the same way, which is used in a normal method.

Some important things about anonymous method:

1. If you declared variable outside the anonymous method, then it can be accessed inside the anonymous method.
2. A variable, declared inside the anonymous method can’t be accessed outside the anonymous method.
3. Anonymous methods can be used in the place where there is a use of a delegate.
4. You cannot access unsafe code within an anonymous method.
5. An anonymous method can’t access the ref or out parameters of an outer scope.
6. Method overloading is not possible for anonymous functions, because it has no name.

Events

An event is an automatic notification to users that some action has occurred. Or you can say that events are user actions such as key press, clicks, etc. When user performs some event, your application should respond by executing function.

Steps for working with events:

1. Create a delegate that will work as event handler.
2. Declare an event with the help of delegate.
3. Register the method with the event.
4. Perform some action for executing the event.

Event handlers are represented by delegates.

The general form of an event is as follows:

event delegate-name event-name;

Example

using System;
namespace ConsoleApplication1
{
    // Declare a delegate for an event.
    delegate void MyEventHandler();
    class SimpleEvent
    {
        public event MyEventHandler MyEvent;
        // This method will fire the event.
        public void OnEvent()
        {
            if (MyEvent != null)
                MyEvent();
        }
    }
    class Program
    {
        static void Handler()
        {
            Console.WriteLine("Hello My Event");
        }
        static void Main(string[] args)
        {
            SimpleEvent eventObject = new SimpleEvent();
            // Add Handler() to the event list.
            eventObject.MyEvent += Handler;
            // Below line will fire the event.
            eventObject.OnEvent();
            Console.ReadLine();
        }
    }
}


In the above program we have craeted a delegate type for the event handler, as shown here:

delegate void MyEventHandler();

Inside the SimpleEvent class, an event called MyEvent is declared with the help of delegate:
        
public event MyEventHandler MyEvent;

You subscribe to an event by using this += operator. When OnEvent() method is called, then event will be fired. Handler method will be called only if MyEvent will not be null.