This post provides a very basic introduction of delegates in C#. Part 2 of this post can be read here. A delegate is a class that is derived from System.Delegate. It contains a list of one or more methods called an invocation list. When a delegate instance is “invoked” with the arguments as defined in the signature of the delegate, each of the methods in the invocation list gets invoked with the arguments. The code below shows example with static and instance methods respectively: Static Methods 1: using System;
2: using System.Linq;
3: using System.Collections.Generic;
4:
5: public delegate void SayName(string name);
6:
7: public class Program
8: {
9: [STAThread]
10: static void Main(string[] args)
11: {
12: SayName englishDelegate = new SayName(SayNameInEnglish);
13: SayName frenchDelegate = new SayName(SayNameInFrench);
14: SayName combinedDelegate =(SayName)Delegate.Combine(englishDelegate, frenchDelegate);
15:
16: combinedDelegate.Invoke("Tom");
17: Console.ReadLine();
18: }
19:
20: static void SayNameInFrench(string name) {
21: Console.WriteLine("J'ai m'appelle " + name);
22: }
23:
24: static void SayNameInEnglish(string name) {
25: Console.WriteLine("My name is " + name);
26: }
27: }
We have declared a delegate of type SayName with return type of void and taking an input parameter of name of type string.
On line 12, we create a new instance of this delegate which refers to a static method - SayNameInEnglish. SayNameInEnglish has the same return type and parameter list as the delegate declaration. Once a delegate is instantiated, the instance will always refer to the same target. Delegates are immutable.
On line 13, we create a new instance of the delegate but point to a different static method.
As you may recall, a delegate instance encapsulates an invocation list. You create an invocation list by combining delegates using the Delegate.Combine method (there is an easier syntax as you will see later). When two non null delegate instances are combined, their invocation lists get combined to form a new invocation list. This is done in line 14. On line 16, we invoke the delegate with the Invoke method and pass in the required string parameter. Since the delegate has an invocation list with two entries, each of the method in the invocation list is invoked.
If an unhandled exception occurs during the invocation of one of these methods, the exception gets bubbled up to the line where the invocation was made (line 16).
If a delegate is null and you try to invoke it, you will get a System.NullReferenceException.
We see the following output when the method is run:
My name is TomJ'ai m'apelle Tom
Instance Methods
The code below outputs the same results as before. The only difference here is we are creating delegates that point to a target object (an instance of Translator) and instance methods which have the same signature as the delegate type. The target object can never be null. We also use the short cut syntax += to combine the delegates instead of Delegate.Combine.
1: public delegate void SayName(string name);
2:
3: public class Program
4: {
5: [STAThread]
6: static void Main(string[] args)
7: {
8: Translator translator = new Translator();
9: SayName combinedDelegate = new SayName(translator.SayNameInEnglish);
10: combinedDelegate += new SayName(translator.SayNameInFrench);
11:
12: combinedDelegate.Invoke("Tom");
13: Console.ReadLine();
14: }
15: }
16:
17: public class Translator {
18: public void SayNameInFrench(string name) {
19: Console.WriteLine("J'ai m'appelle " + name);
20: }
21:
22: public void SayNameInEnglish(string name) {
23: Console.WriteLine("My name is " + name);
24: }
25: }
A delegate can be removed from a combination of delegates by using the –= operator. Removing a delegate from an empty list or removing a delegate that does not exist in a non empty list will not result in an exception. Delegates are invoked synchronously using the Invoke method. We can also invoke them asynchronously using the BeginInvoke and EndInvoke methods which are compiler generated.