Delegates With A Real Time Example In C#

What is a delegate?

  • It is a reference type.
  • It is a function pointer or it holds a reference (pointer) to a function (method).
  • It is type safe.
  • Delegates are mainly used for the event handling and the callback methods.

Explanation

  1. Let’s create a simple function to display the message, as shown below.
    1. public static void PrintMessage(string msg)  
    2.         {  
    3.             Console.WriteLine(msg);  
    4.         }  
  2. Now, create a delegate to refer this function, as shown below.

    To create a delegate, use the keyword delegate and remaining same as method signature.

            
     public delegate       void    PrintMsgFunctionDelgate(string Message);

    Here, this delegate has return type void and one string parameter. This delegate can be used to point to any function, which has a similar signature i.e., it can be used to point to any function, which has void return type and one string parameter.

  3. Now, let’s see how we will make this delegate point to the function PrintMessage.

    To do this, we have to create an instance of this delegate and this is where a delegate is similar to a class. To create an instance of a delegate, proceed as shown below.



    You can see the intellisence is telling that to pass the method name, which is having void return type and the string parameter, the function PrintMessage has the same signature, so I am passing it, as shown below.

    PrintMsgFunctionDelgate print = new PrintMsgFunctionDelgate(PrintMessage);

  4. To invoke that method, all we have to do is to invoke this delegate, as shown below. It is similar like function calls,
    1. print("welcome");  
    This delegate will call PrintMessage function indirectly.

If you are pointing to a function, which has a different signature, you will get a compiler error, as shown below.

In the example given below, my function return type is string and delegate return type is void.



Real time example

Let’s create a class employee

  1. class Employee  
  2.     {  
  3.         public int ID { get; set; }  
  4.         public string Name { get; set; }  
  5.         public int salary { get; set; }  
  6.         public float Experiance { get; set; }  
  7.   
  8.         public static void PromoteEmp(List<Employee> EmployeeList)  
  9.         {  
  10.             foreach (Employee  emp in EmployeeList )  
  11.             {  
  12.                 if(emp.Experiance>=5)//logic condition  
  13.                 {  
  14.                     Console.WriteLine(emp.Name + " promoted");  
  15.                 }  
  16.             }  
  17.         }  
  18.     }  
Now, I wanted to make this class reusable, but right now it is not. As you can see here, this class has a hard coded condition for promoting employee. Sometimes an employee will be promoted based on salary. For example, whosoever has a  salary more than 15,000. In this case, we have to go and edit these hard coded conditions. This is not the right way. We have to change this class, so that without changing the condition inside the class, they can promote the employees there. As per logic, we can use delegate.

Before using delegate, let’s call this class and see how the output will be
  1. public static void Main()  
  2.         {  
  3.             List<Employee> empl = new List<Employee>();  
  4.             empl.Add(new Employee() { ID = 101, Name = "Ravi", salary = 20000, Experiance = 3 });  
  5.             empl.Add(new Employee() { ID = 102, Name = "John", salary = 30000, Experiance = 5 });  
  6.             empl.Add(new Employee() { ID = 103, Name = "Mary", salary = 50000, Experiance = 8 });  
  7.             empl.Add(new Employee() { ID = 104, Name = "Mike", salary = 10000, Experiance = 2 });  
  8.             Employee.PromoteEmp(empl);  
  9.         }  
The output would be as shown below.



Now, let’s see how this PromoteEmp method inside class makes it reusable, using delegate.
  1. Create delegate that points to the function, which checks the condition and returns true or false by passing an Employee object, as shown below.

    delegate bool isPromote(Employee emp);

  2. Now, we will replace that, if the condition expression is with that delegate. For this, I am going to pass this delegate as a parameter to the function PromoteEmp and in if condition expression, I am going to call this delegate with an employee object, as shown below.
    1. public static void PromoteEmp(List<Employee> EmployeeList,isPromote IsEligible)  
    2.         {  
    3.             foreach (Employee  emp in EmployeeList )  
    4.             {  
    5.                 if(IsEligible(emp))//logic condition  
    6.                 {  
    7.                     Console.WriteLine(emp.Name + " Promoted");  
    8.                 }  
    9.             }  
    10.         }  
    Now, you can see that there is no hard coded logic to promote an employee. The logic is used when we call this method.

    The logic is written in a separate function, as shown below.
    1. Public static bool promote(Employee emp)  
    2.         {  
    3.             if (emp.Experiance >= 5)  
    4.             {  
    5.                 return true;  
    6.             }  
    7.             else  
    8.             {  
    9.                 return false;  
    10.             }  
    11. }  
    Here, you can write your own logic but it should return true or false.

Passing this logic and promote employee is shown below.

  1. Creating an instance of delegate
    1. isPromote pro = new isPromote(promote);   
  2. Calling PromoteEmp function with passing the employee list and the delegate is given below.
    1. Employee.PromoteEmp(empl, pro);  
    The full code is given below.
    1. public static void Main()  
    2.         {  
    3.             List<Employee> empl = new List<Employee>();  
    4.             empl.Add(new Employee() { ID = 101, Name = "Ravi", salary = 20000, Experiance = 3 });  
    5.             empl.Add(new Employee() { ID = 102, Name = "John", salary = 30000, Experiance = 5 });  
    6.             empl.Add(new Employee() { ID = 103, Name = "Mery", salary = 50000, Experiance = 8 });  
    7.             empl.Add(new Employee() { ID = 104, Name = "Mike", salary = 10000, Experiance = 2 });  
    8.   
    9.             isPromote pro = new isPromote(promote);  
    10.             Employee.PromoteEmp(empl, pro);  
    11.         }  
    12.   
    13.         public static bool promote(Employee emp)  
    14.         {  
    15.             if (emp.Experiance >= 5)  
    16.             {  
    17.                 return true;  
    18.             }  
    19.             else  
    20.             {  
    21.                 return false;  
    22.             }  
    23.         }  
    24.     
    25.     }  
    26.      
    27.     delegate bool isPromote(Employee emp);  
    28.     class Employee  
    29.     {  
    30.         public int ID { get; set; }  
    31.         public string Name { get; set; }  
    32.         public int salary { get; set; }  
    33.         public float Experiance { get; set; }  
    34.   
    35.          
    36.         public static void PromoteEmp(List<Employee> EmployeeList,isPromote IsEligible)  
    37.         {  
    38.             foreach (Employee  emp in EmployeeList )  
    39.             {  
    40.                 if(IsEligible(emp))//logic condition  
    41.                 {  
    42.                     Console.WriteLine(emp.Name + " Promoted");  
    43.                 }  
    44.             }  
    45.         }  
    46. }  

There are two types of delegates, which are given below.

  • Unicast deligate

    This delegate refers to only one method, as shown in the above examples.

  • Multicast deligate

    This delegate can refer to more than one method. This delegate maintains a list of the methods.
    Example,
    1. delegate void strDele(string str); //declare  
    2. strDele delobj += new strDele (uppercasestr); //method reference 1  
    3. delobj += new strDele (Lowercasestr); //method reference 2   
    4. delobj(“Welcome”); //invoking the multicast delegate  

Note

An instance of a delegate can refer to static as well as instance methods. The signature of function declaration and the delegate declaration should match.