C# Delegates and Events

    1 Votes


The delegates in C# are similar to the function pointer in C or C++. It is an object that refers to a method. By using delegate it allows the programmer to encapsulate a reference to a method inside the delegate object. Then this object can be passed to the code which can call the referenced method without having to know at compile time which method will be invoked.

The delegates are objected oriented, type safe and secure. It defines a type that encapsulates the method with a particular set of arguments and return type. We can use delegates without parameters or with parameter list. The delegate does not know about the class of the object that it references. It can be bound to a single or multiple methods which are referred as multicasting. Delegates are the basis for Events. A delegate can be instantiated by associating it either with a named or anonymous method.

Steps to create delegate:

Declaring delegate
  • delegate result-type identifier([parameter])
  • result- type- return type of the function
  • identifier – delegate name
  • parameter – that the function take.
  • public delegate void SimpleDelegate();
Instantiating the delegate
SimpleDelegate obj1=new SimpleDelegate(function name)
Invocation : obj1();
Let us have an example:
using System;
   delegate int Calculate(int n1,int n2);
    class Program
    {
        public static int Multiply(int i,int j)
        {
            return (i * j);
        }
        public static int add(int i, int j)
        {
            return (i + j);
        }
        static void Main(string[] args)
        {
            int a = 90;
            int b = 78;
            Calculate obj1 = new Calculate(Program.add);
            Console.WriteLine("result is" + obj1(a, b));
            Calculate obj2 = new Calculate(Program.Multiply);
            Console.WriteLine("result of Multiplication  is" + obj2(a, b));
            Console.ReadKey();
        }
}

Output:
result is168
result of Multiplication is7020

Advantages of Delegates:

  • It is a support for events.
  • It can execute methods at run time.
  • It provides reusability of code.
  • It provides great amount of flexibility.

Multicasting

In multicasting the delegate can call more than one method when invoked. The multicast delegate maintains a list of functions that will be called when the delegate is invoked. When the delegate function is called, each of the referenced methods is executed in turn; the execution is in the same order in which references are added.

Multicast delegates are used extensively in event handling. By using the addition or addition assignment operators ('+' or '+='), we can add the method references. By comparing delegates of two different types assigned at compile-time will result in a compilation error. Only delegates of the same type can be combined. The - operator can be used to remove a component delegate from a multicast delegate.

Let us have an example:

using System;
delegate void Del(string s);
class TestClass
{
    static void Hello(string s)
    {
        Console.WriteLine ("  Hello, {0}!", s);
    }
    static void Goodbye(string s)
    {
        Console.WriteLine ("  Goodbye, {0}!", s);
    }
    static void Main()
    {
       Del a, b, c, d;
       a = Hello;
       b = Goodbye;  
       c = a + b;       
       d = c - a;
        Console.WriteLine ("Invoking delegate a:");
        a("A");
        Console.WriteLine ("Invoking delegate b:");
        b("B");
        Console.WriteLine ("Invoking delegate c:");
        c("C");
        Console.WriteLine ("Invoking delegate d:");
        d("D");
    }
}

Output:
Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!

Delegates v/s Interfaces

The delegates and interfaces are similar as they enable the separation of specification and implementation. The multiple independent authors can produce the implementations that are compatible with an interface specification. A delegate specifies the signature of a method and authors can write methods that are compatible with.

Delegates are useful when:

  • The single method is being called.
  • The class may want to have multiple implementations of the method specification.
  • It is desirable to allow using a static method to implement the specification.
  • An event-like design pattern is desired.
  • The caller has no need to know or obtain the object that the method is defined on.

Interfaces are useful when:

  • The specification defines a set of related methods that will be called.
  • A class typically implements the specification only once.
  • The caller of the interface wants to cast to or from the interface type to obtain other interfaces or classes.

Anonymous Method:

An anonymous method provides a technique to pass the code block as a delegate parameter. These methods are without name, there is only body. In this method there is no need to specify the return type. It is inferred from the return statement inside the method body. This method was added by C# 2.0.

It cannot access the ref or out parameters of an outer scope. Within the anonymous method block no unsafe code can be accessed. The anonymous methods are not allowed on the left side of the operator.

Let us have a look on the example:

using System;
delegate int Math(int a, int b);
class Program
{
 //delegate for representing anonymous method
 delegate int del(int x, int y);
 static void Main(string[] args)
 {
 //anonymous method using delegate keyword
 del d1 = delegate(int x, int y)
 {
     return x + y; 
 };
 int z1 = d1(2, 3);
 Console.WriteLine ("Anonymous Method:" +z1);
 }
}

Output:
Anonymous Method: 5

Lambda Expression

The lambda expression is an anonymous function that contains expressions and statements and it can be used to create delegates or expression tree types. All the lambda expressions use the lambda operator => which is read as “goes to”. The left side of the lambda operator specifies the input parameters and the right side hold the expressions or statement block.

For example: a=>a * a is read as “a goes to a times a”. The => operator has the same precedence as the assignment (=) and is right associative. They are not allowed on the left side of the is or as operator. They can be assigned to a delegate. There are two types of lambda expressions:

Expression Lambda – It consists of single expression and it is not enclosed between braces.For example: (input parameters) => expression

The parentheses are optional only if the lambda has one input parameter, otherwise they are required. In this expression lambda two or more input parameters are separated by commas which are enclosed in parentheses. Like

(a, b)=>a = = b

Let us have an example to understand it:

using System;
delegate int IntOp(int end);
class Program
{
   static void Main()
  {
     IntOp fact= n=> 
     {
         int r=1;
         for(int i=1;i<=n;i++)
              r= i*r;
              return r;
     };
Console.WriteLine ("The factorial is" + fact(3));
Console.WriteLine ("The factorial is" + fact(5));
}
}   

Output:
The factorial is 6
The factorial is 120

Events

The C# is an object oriented language and also event driven. The events enable a class or an object to notify the other classes or objects when some activities occur. The basic model is publisher and subscriber. The class that sends the event is known as publisher and the classes that receive the event are known as subscribers.

In C#, any of the objects can publish a set of events to which other applications can subscribe. The publisher determines when an event is raised and the subscribers determine what the action is to be taken in response to an event. The event can have the multiple subscribers. A subscriber can handle the multiple events from multiple publishers. Events that have no subscribers are never raised. Let us have an example to understand it:

using System;
using System.IO;
namespace ConsoleApplication1
{delegate  void MyEventHandler();
    class MyEvent
    {
        public event MyEventHandler SomeEvent;
        public void OnSomeEvent()
        {
            if (SomeEvent != null)
                SomeEvent();
        }
    }
    class Program
    {
        static void handler()
        {
             Console.WriteLine("Event occured");
        }
        static void Main(string[] args)
        {

            MyEvent evt = new MyEvent();
            evt.SomeEvent += Program.handler;
            evt.OnSomeEvent();
            Console.ReadKey();
        }
}
}

Output: Event occured