C# Delegates

What is a Delegate?
A delegate is a special kind of object that holds a reference to a method. The delegate can be called as if it were any other method. However, when called, the underlying referenced method is executed. This simple layer of abstraction is useful because unlike a direct call, the method being used does not need to be known when writing the code. The reference is created at run-time and may be changed repeatedly throughout the life of the executing program.
NB: If you have previously used C++ function pointers then you will see many similarities between these and delegates. Unlike function pointers, C# delegates are object-oriented, secure and type-safe.
Multicasting
Delegates provide a useful facility known as multicasting. When a delegate is used for multicasting, two or more method references may be added to the delegate object. In this situation, a single call to the delegate function actually calls each of the added methods in turn. The combination of the referenced items is known as the invocation chain or invocation list.
Asynchronous Callbacks
Another interesting use of delegates is known as asynchronous callback. As a delegate is an object, it may be passed as a parameter or assigned as the value of a property. This allows a delegate to be created and passed to a long-running, asynchronous process. When the process has finished executing, the delegate can be called to indicate completion. Asynchronous callbacks are beyond the scope of this article.
Creating a Delegate
To create a delegate, the delegate keyword is used as a prefix to the method’s signature as follows:

delegate return-type name(parameters);

The return-type is the data type that will be returned from a method that is referenced by the delegate. The name is the name of the delegate and the parameters section contains the comma-separated list of parameters used when calling the delegate. The return-type and parameters form the signature of the delegate and this must match the signature of the method that is linked to it, though the reference method may be static or linked to a particular instance of a class.
Creating a Simple Delegate
To demonstrate the declaration and use of a simple delegate we will create a program as an example. To begin, create a new console application named “DelegateDemo”. Add a class file named “Scoreboard” to the project. This class will hold methods that calculate a score for a fictitious game that requires the player to hit targets in the quickest time possible. Versions of the calculation will be available for adults and children and we will use a delegate to determine which is used.
Add the following code to the Scoreboard class to create the two scoring mechanisms:

// 10 points per target, -2 point per second
public static int CalculateAdultScore(int seconds, int targets)
{
return (targets * 10) - (seconds * 2);
}
// 15 points per target, -1 point per second
public static int CalculateChildScore(int seconds, int targets)
{
return (targets * 15) - seconds;
}

Declaring the Delegate
We will assign which scoring calculation is used at run-time within the Main method of the program. To be able to change the scoring method at run-time, a delegate must be declared. The delegate can be declared either within the class, in which case it is available only to that class’ members, in the namespace so that it is available to all contained classes or outside of the namespace to be globally visible. In this case, add the following code within the application’s “Program” class.

delegate int CalculateScore(int seconds, int targets);

NB: In the sample the parameters have the same names as those of the methods that will be referenced by the delegate. This is not a requirement though the data types must match.
Referencing a Method
Finally we need to link a target method to the delegate so it can be called. Add the following code to the Main method:

CalculateScore getScore;
int time = 60;
int targets = 20;
getScore = new CalculateScore(Scoreboard.CalculateAdultScore);
Console.WriteLine("Adult score: {0}", getScore(time, targets));
getScore = new CalculateScore(Scoreboard.CalculateChildScore);
Console.WriteLine("Child score: {0}", getScore(time, targets));

/* OUTPUT
Adult score: 80
Child score: 240
*/

The code in the Main method starts by declaring an object named “getScore” based upon the Calculate Score delegate. This object will be called instead of the target method that is assigned at run-time. The two integers simply represent the data for the time taken and the number of targets hit that will be used to calculate a score.
Next, the getScore object is initialized. This is similar in syntax to instantiating any other object. The key difference is that the parameter that is required is a reference to the method that is to be linked to the delegate object. In this case, because the called method is static, the class and method names are provided. If this were an instance method, you would substitute the class name with the name of an object.
The first Console.WriteLine statement outputs the calculated score using adult scoring rules. It does this by calling the getScore delegate object as if it were the referenced method. The delegate effectively passes control to the CalculateAdultScore method.
Finally, the getScore object is re-instantiated, this time using the children’s scoring mechanism. When the method is executed for the second time, the outputted score is therefore different.
Removing the Reference
Once a delegate’s method reference is no longer required, it should be removed. This provides more efficient garbage collection and release of resources when required. To remove the reference, simply set the object’s value to null. For the scoring example above, the following code is used:

getScore = null;

Creating a Multicasting Delegate
Earlier in the article I mentioned multicasting delegates. These interesting variants on the standard delegate permit multiple methods to be referenced by a single delegate object. When the delegate function is called, each of the referenced methods is executed in turn. In the case of the delegates that we will create in the remainder of this article, the execution order is the same as the order in which the references are added.
To demonstrate the declaration and use of a multicasting delegate we will modify the Scoreboard class and the Main method of the previously created program. We will start by adding two methods to the Scoreboard class, each providing a facility to output a status message to the console.
Add the following code to the Scoreboard class to create the two status message methods:

// Target hit message
public void TargetHit()
{
Console.WriteLine("Target hit!");
}
// Points awarded message
public void PointsAwarded()
{
Console.WriteLine("Points awarded!");
}

NB: Note that this time we are using instance rather than static methods so will be calling the methods of an instantiated Scoreboard object.
Declaring the Delegate
Declaring a multicasting delegate is no different to declaring a simple one. To create the new delegate, add the following code within the application’s “Program” class.

delegate void ShowStatus();

Referencing Multiple Methods
Adding the first method to the delegate uses the same syntax used in the previous example. To add the second and subsequent method references, the addition compound assignment operator (+=) is used. The following code shows this by executing both of the status display methods from a single delegate call. To test the sample, replace the contents of the Main method with the code below:

Scoreboard board = new Scoreboard();
ShowStatus points = new ShowStatus(board.PointsAwarded);
ShowStatus hit = new ShowStatus(board.TargetHit);
ShowStatus display = points;
display += hit;
display();

/* OUTPUT
Points awarded!
Target hit!
*/

In this code, an instance of Scoreboard is needed so this is declared first, followed by an individual declaration for two delegates to reference the two methods. The “display” delegate, which will be the multicast delegate is then created and assigned the value of “points”. Using the compound assignment operator the second delegate is added to the invocation chain so that when display is called, both of the underlying methods are executed.
Removing the References
As with simple delegates it is important to release the references when they are no longer required. To release all of the references at once, the delegate objects can be simply set to null as described earlier.
However, sometime you will want to unsubscribe single references. This is achieved by using the subtraction compound operator. For example, to unsubscribe and release the “points” reference, you would use the following code:

display -= points;
points = null;

Tagged , . Bookmark the permalink.

5 Responses to C# Delegates

  1. Fred says:

    Very clear. Thanks

  2. Adam says:

    Thanks a million this is cristal clear
    God bless you maan

  3. Ram says:

    Hi..
    Instead of creating a object for delegate and calling those methods why dont we create objects for class and call it.. creating an object for class and calling those methods is also same like calling methods wit delegates..
    pls say the difference….

    • Hi Ram,
      If you creating an object of a class and use it instead of delegate in that case it will create a new object or a new instance of a class and call default constructor but if you are using delegate in that case class default constructor calls only one time at the initialization of the page. Suppose I want to user control button click event on the aspx page code then Delegate is the best way to call user control’s button event on aspx code page. This is the simplest and best example to understand delegates.
      Thanks & Keep Reading…..

  4. alex says:

    Thanks, very clear!

Leave a Reply