C# – Delegates

In this post, we will see what Delegates are and how to use them.
First of all, what is a Delegate?
From Microsoft web site:
“A delegate is a type that safely encapsulates a method, similar to a function pointer in C and C++. Unlike C function pointers, delegates are object-oriented, type safe, and secure. The type of a delegate is defined by the name of the delegate”
In a nutshell, when we define a variable as a “Delegate” we can use it in order to run some methods that have the same signature defined in our Delegate.


[SINGLECAST DELEGATE]
We define a class called “Operations” and we add two methods called “Sum” and “Subtraction”:

internal class Operations
{
   public static string Sum (int val1, int val2)
   {
      return $"The result of {val1} + {val2} is: {val1 + val2}";
   }

   public static string Subtraction (int val1, int val2)
   {
      return $"The result of {val1} - {val2} is: {val1 - val2}";
   }
}


Now, we will use a Delegate in order to run these two methods:

 // Definition of a delegate
public delegate string DelegateOperations(int val1, int val2);

static void Main(string[] args)
{
    // set the delegate with the Sum operation
    DelegateOperations delOperations = Operations.Sum;

    // invoke the delegate
    Console.WriteLine(delOperations(5, 6));

    // set the delegate with the Subtraction operation
    delOperations = Operations.Subtraction;

    // invoke the delegate
    Console.WriteLine(delOperations(15, 6));
}


If we run the code, this will be the result:



Obviously, we can use a Delegate with a void methods:

// Definition of a delegate
public delegate void DelegatePrintOperations(int val1, int val2);

static void Main(string[] args)
{
   // set the delegate with the PrintSum method
   DelegatePrintOperations delOperations = Operations2.PrintSum;

   // invoke the delegate
   delOperations(5, 6);

   // set the delegate with the PrintSubtraction method
   delOperations = Operations2.PrintSubtraction;

   // invoke the delegate
   delOperations(15, 6);
}


internal class Operations2
{
   public static void PrintSum(int val1, int val2)
   {
       Console.WriteLine($"The result of {val1} + {val2} is: {val1 + val2}");
   }

   public static void PrintSubtraction(int val1, int val2)
   {
       Console.WriteLine($"The result of {val1} - {val2} is: {val1 - val2}");
   }
}


and we can use a Delegate with no static methods:

// Definition of a delegate
public delegate void DelegatePrintOperations(int val1, int val2);

static void Main(string[] args)
{
   // create an instance of the Operations3 class
   var ope3 = new Operations3();

   // set the delegate with the PrintSum method
   DelegatePrintOperations delOperations = ope3.PrintSum;

   // invoke the delegate
   delOperations(5, 6);

   // set the delegate with the PrintSubtraction method
   delOperations = ope3.PrintSubtraction;

   // invoke the delegate
   delOperations(15, 6);
}

internal class Operations3
{
   public void PrintSum(int val1, int val2)
   {
       Console.WriteLine($"The result of {val1} + {val2} is: {val1 + val2}");
   }

   public void PrintSubtraction(int val1, int val2)
   {
       Console.WriteLine($"The result of {val1} - {val2} is: {val1 - val2}");
   }
}



If we try to use a method with a different signature, we will have a compile error:

// Definition of a delegate
public delegate void DelegatePrintOperations(int val1, int val2);

static void Main(string[] args)
{
    // set delegate with the Sum operations
    DelegateOperations delOperations = Operations.Square;
    ...
    ...
    ...
}

internal class Operations
{
   public static string Sum (int val1, int val2)
   {
      return $"The result of {val1} + {val2} is: {val1 + val2}";
   }

   public static string Subtraction (int val1, int val2)
   {
      return $"The result of {val1} - {val2} is: {val1 - val2}";
   }

   public static string Square(int val1)
   {
      return $"The result of {val1} squared is: {val1*val1}";
   }
}


Finally, we can pass a delegate as an input parameter in a method:

// Definition of a delegate
public delegate void DelegatePrintOperations(int val1, int val2);

static void Main(string[] args)
{
    // set the delegate with the Sum operation
    DelegatePrintOperations delOperations = Operations2.PrintSum;

    // call a method passing in input the delegate
    PrintResult(delOperations);

    // set the delegate with the Sum operation
    delOperations = Operations2.PrintSubtraction;

    // call a method passing in input the delegate
    PrintResult(delOperations);
}

static void PrintResult(DelegatePrintOperations delegateOperations)
{
    delegateOperations(15, 6);
}


internal class Operations2
{
    public static void PrintSum(int val1, int val2)
    {
       Console.WriteLine($"The result of {val1} + {val2} is: {val1 + val2}");
    }

    public static void PrintSubtraction(int val1, int val2)
    {
        Console.WriteLine($"The result of {val1} - {val2} is: {val1 - val2}");
    }
}




[MULTICAST DELEGATE]
A delegate that points multiple methods, is called a multicast delegate.
The “+” or “+=” operator adds a function to the invocation list, and the “-” and “-=” operator removes it.
Let’s see some examples:

// Definition of a delegate
public delegate void DelegatePrintOperations(int val1, int val2);

static void Main(string[] args)
{
   // definition of two delegates
   DelegatePrintOperations delOperations = Operations2.PrintSum;
   DelegatePrintOperations delOperations2 = Operations2.PrintSubtraction;

   // definition of a delegate that will use both the methods
   // we can define finalDelOperations in this way too:
   // DelegatePrintOperations finalDelOperations = delOperations + delOperations2;
   DelegatePrintOperations finalDelOperations = delOperations;
   finalDelOperations += delOperations2;
   finalDelOperations(10, 5);
}
...
...
...


If we run the code, this will be the result:


Now, we remove a method:

// Definition of a delegate
public delegate void DelegatePrintOperations(int val1, int val2);

static void Main(string[] args)
{
    // set delegate with the Sum operation
    DelegatePrintOperations delOperations = Operations2.PrintSum;
    DelegatePrintOperations delOperations2 = Operations2.PrintSubtraction;

    // we can define finalDelOperations in this way too:
    // DelegatePrintOperations finalDelOperations = delOperations + delOperations2;
    DelegatePrintOperations finalDelOperations = delOperations;
    finalDelOperations += delOperations2;

    finalDelOperations(10, 5);

    // we remove the delOperations (Operations2.PrintSum)
    finalDelOperations -= delOperations;

    Console.WriteLine();
    finalDelOperations(10,5);
}
...
...
...


If we run the code, this will be the result:




[ANONYMOUS DELEGATE]
We can create a delegate without to declare a method associated with it and our delegate itself contains the method definition:

 // Definition of a delegate
 public delegate int DelegateAnonymous(int val1);

static void Main(string[] args)
{
    DelegateAnonymous objDeleAnonymous = delegate(int val1) { return val1 * val1; };

    Console.WriteLine(objDeleAnonymous(5));

    objDeleAnonymous = delegate (int val1) { return val1 * val1 * val1; };

    Console.WriteLine(objDeleAnonymous(5));
}


If we run the code, this will be the result: