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.