You are on page 1of 5

Delegates in C#

Definition:
The idea of a delegate in a nutshell is as follows:

“A delegate is a type the values of which consist of methods”

Explanation:
Delegates allow us to work with variables and parameters that contain methods
Thus, a delegate in C# defines a type, in the same way as a class defines a type. A delegate
reflects the signature of a set of methods, not including the method names, however. A
delegate is a reference type in C#. It means that values of a delegate type are accessed via
references, in the same way as an object of a class always is accessed via a reference. In
particular, null is a possible delegate value.
A delegate is a class that encapsulates a method signature. Although it can be used in any
context, it often serves as the basis for the event-handling model in C# but can be used in a
context removed from event handling (e.g. passing a method to a method through a delegate
parameter).
Since delegates are classes, they have instances (delegate objects). Such delegate instances
contain references to one or more methods. A delegate instance is connected to one or more
methods using a delegate constructor and later using simple operators. The methods that a
delegate instance is associated with (invocation list) are invoked through the delegate instance.
A delegate defines the signature (return type and sequence of parameter types) of the methods that
can be added to the invocation list of a delegate instance. If an attempt is made to add a method to
a delegate object’s invocation list that does not confirm precisely to the signature in the delegate
class, a compilation error is emitted.
Syntax for delegate declaration is:

delegate <return type> <delegate-name> <parameter list>

An example of a delegate class declaration is the following:

public delegate String SomeDelegate(int x, double y, char z);

Instances of a delegate class are created as indicated in the following examples:

SomeDelegate d1 = new SomeDelegate(Method1);


SomeDelegate d2 = new SomeDelegate(Method2);
The invocation list for delegate instance d3 is Method2 and Method3.

An example of invoking the method(s) on the invocation list of a delegate would be the
following:

String result = d3(16, 4.1, ‘a’);

The return value is always associated with the last method in the invocation list, Method2 in this
case. Often delegates are associated with methods that return void (commands) so there is no
return value to be concerned about.
Like all classes, delegates can be top-level classes within a namespace or be nested within an
existing class. The same access modifiers that can be applied to classes apply for delegates.
Delegates can contain generic parameters or return type.

Main Three Pieces of Information Maintained by Delegates:


1. The name of the method which it makes calls
2. The argument(if any) of this method
3. The return value(if any) of this method

Instantiating Delegates:
Once a delegate type has been declared, a delegate object must be created with the new
keyword and be associated with a particular method. When creating a delegate, the argument
passed to the new expression is written like a method call, but without the arguments to the
method. For example:
public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);

Following example demonstrates declaration, instantiation and use of a delegate that can be used
to reference methods that take an integer parameter and returns an integer value.
using System;

delegate int NumberChanger(int n);


namespace DelegateAppl
{
class TestDelegate
{
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}

public static int MultNum(int q)


{
num *= q;
return num;
}
public static int getNum()
{
return num;
} static void
Main(string[] args)
{
//create delegate instances
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum); //calling the
methods using the delegate objects nc1(25);
Console.WriteLine("Value of Num: {0}", getNum()); nc2(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}

When the above code is compiled and executed, it produces the following result:

Value of Num: 35
Value of Num: 175

Multicasting of a Delegate
Delegate objects can be composed using the "+" operator. A composed delegate calls the two
delegates it was composed from. Only delegates of the same type can be composed. The "-"
operator can be used to remove a component delegate from a composed delegate.

Using this useful property of delegates you can create an invocation list of methods that will
be called when a delegate is invoked. This is called multicasting of a delegate.
The following program demonstrates multicasting of a delegate:
using System;

delegate int NumberChanger(int n);


namespace DelegateAppl
{
class TestDelegate
{
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}

public static int MultNum(int q)


{
num *= q;
return num;
}
public static int getNum()
{
return num;
}

static void Main(string[] args)


{
//create delegate instances
NumberChanger nc;
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
nc = nc1; nc += nc2;
//calling multicast
nc(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}

When the above code is compiled and executed, it produces the following result:

Value of Num: 75
Use of delegates:
There are 6 important uses of delegates:-

1. Abstract and encapsulate a method (Anonymous invocation)


This is the most important use of delegates; it helps us to define an abstract pointer which can point to
methods and functions. The same abstract delegate can be later used to point to that type of functions
and methods. In the previous section we have shown a simple example of a maths class. Later addition
of new algorithm functions does not affect the UI code.

2. Callback mechanism: Many times we would like to provide a call back mechanism. Delegates can be
passed to the destination and destination can use the same delegate pointer to make callbacks.

3. Asynchronous processing: by using ‘BeginInvoke’ and ‘EndInvoke’ we can call delegates


asynchronously. In our previous section we have explained the same in detail.

4. Multicasting - Sequential processing: Sometime we would like to call some methods in a sequential
manner which can be done by using multicast delegate. This is already explained in the multicast
example shown above.

5. Events - Publisher subscriber model: we can use events to create a pure publisher / subscriber
model.

You might also like