Thursday, November 19, 2015

Delegates in C#

In today's blog post, we will be discussing delegates in C#.

Delegates

Simply put, a delegate is a type safe function pointer. It defines the signature of the method that can be used. The delegate can point to any method as long as the signature of the method is the same. The signature here includes the parameter types and return types.

delegates in C#

Let's take a look at a simple example of delegates and see how they can be useful. Let's have our favorite Employee class like this:

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime StartDate { get; set; }
}
Suppose, we want to find out all the employees who can be promoted. So we might write our code something like this:

static bool IsEmployeePromotable(Employee employee) 
{
   if (DateTime.Now.Year - employee.StartDate.Year > 5)
         return true;

    return false;
}

static void Main(string[] args)
{
    var employees = new List<Employee>()
    {
        new Employee(){Id = 1, Name = "Abhi", StartDate = new DateTime(2010,1,1)},
        new Employee(){Id = 2, Name = "John", StartDate = new DateTime(2005,1,1)}
    };

   foreach (var emp in employees) 
   {
        if (IsEmployeePromotable(emp))
       {
          Console.WriteLine("Id = " + emp.Id);
          Console.WriteLine("Name = " + emp.Name);
       }
   }
    Console.ReadLine();
}

So here the program prints all the employees who has more than 5 years of experience in the company. So this looks fine and short.
Suppose, we have some more requirements that want to change the promotion criteria. This will lead us to change the existing code. For any new criteria to be added we will have to change the existing code again and again.  Delegates can help us here as we can inject the promotion criteria on the fly. Let's see how we can do that using delegates:

public delegate bool PromotableEmployee(Employee employee);
static void Main(string[] args)
{
    var employees = new List<Employee>()
    {
        new Employee(){Id = 1, Name = "Abhi", StartDate = new DateTime(2010,1,1)},
        new Employee(){Id = 2, Name = "John", StartDate = new DateTime(2005,1,1)}
    };
    PromotableEmployee IsEmployeePromotable = new PromotableEmployee(IsEmployeeFiveYearsOld);
    foreach (var emp in employees) 
    {
        if (IsEmployeePromotable(emp))
        {
            Console.WriteLine("Id = " + emp.Id);
            Console.WriteLine("Name = " + emp.Name);
        }
    }
    Console.ReadLine();
}

static bool IsEmployeeFiveYearsOld(Employee employee)
{
    if (DateTime.Now.Year - employee.StartDate.Year > 5)
        return true;
    return false;
}

So here I created a delegate type called PromotableEmployee. This type can have any method assigned to it as long as it conforms to the signature. We have this method called IsEmployeeFiveYearsOld() which conforms to the signature. When we created the delegate instance called IsEmployeePromotable which uses IsEmployeeFiveYearsOld() method. And then we use the delegate instance in our program. When we create the delegate instance, we can assign any method to it as long as it conforms to the signature. That's the power of the delegates. 
So I can create any new PromotionCriteria and add it to the code base. Then we can inject that method on the fly.

Conclusion

Delegates are powerful feature of C# and have improved a lot over different versions of C#. I will be discussing multicast delegates in the next post which will show how delegates can be more useful to us.
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 :)

1 comment:

  1. The code:

    if (DateTime.Now.Year - employee.StartDate.Year > 5)
    return true;
    return false;

    ...can be simplified as:

    return (DateTime.Now.Year - employee.StartDate.Year > 5);

    ReplyDelete