C# Delegates

A "delegate" is a type that allows us to have references to methods having a specific parameter list and return type (together called the "signature" of the method). There is a Delegate class and a MulticastDelegate class, but we do not refer to these directly; we use the keyword "delegate".

The format for this looks like this:

     public delegate return-type Name(parameter list);

where the return-type and the details of the parameter list together make up the signature.

For example:

     public delegate void Calculate(int x, int y);

This essentially gives us a new parameterized type called Calculate whose parameter is the signature of the method. We can instantiate it (declare a variable of type Calculate):

     Calculate C;

and we can initialize C to any method with the same signature (parameter list and return type).

If we have

     void Add(int X, int Y) 
     { 
      Console.WriteLine("Sum = {0}", X + Y); 
     }

we could instead write

     Calculate C = Add;

and we could later call the delegate:

C(3, 5);

and the effect is to execute the Add method.

Thus C is a reference to the Add method. In some other languages, we could have a pointer to a function; in C#, we have a delegate. The user of the delegate does not necessarily know anything about the implementation of the method.

A "multicast" delegate can have a list of methods to be invoked, not just one. (When we use keyword "delegate", we get a multicast delegate.) Suppose we have more methods:

     void Subtract(int X, int Y)
     {
      Console.WriteLine("Difference = {0}", X - Y);  
     }

     void Multiply(int X, int Y)
     {
      Console.WriteLine("Product = {0}", X * Y); 
     }

The delegate Calculate can refer to both Add, Subtract and Multiply, in that order. To arrange for this:

     Calculate C = Add;
     C = C + Subtract;   // or the += operator could be used here
     C = C + Multiply;

Now C has a linked list of methods (three of them), and if we execute C, we will execute all three methods: Add (first), Subtract, Multiply.

We could remove one of them from the list:

     C = C - Subtract;  // or the -= operator could be used here

Now C has a list of just two methods: Add and then Multiply.

This is useful if we can predict that sometimes we will want to call a number of methods (of the same signature) one after another. This makes sense mostly if the return type of the methods is void; if the methods return actual values, we probably have no way to make use of them.

We could have multiple delegates with the same signature:

     Calculate C;
     Calculate D;

We could define multiple delegates with different signatures.

Comment: The term "signature" is used several different ways. When used elsewhere, it does not always include the return type of a method.