Purpose of Delegates in C# (C Sharp)

In your application, how do you handle events? Or Do you have to use a method wherein the method name can be determined only at run time? Or at any situation, did you prefer having functional pointer concept of C++ in C#? If so, then you can use “Delegates” to achieve it.

Delegates are used to wrap a method. You can invoke that method by calling the delegate. In other words, delegates are methods that accept another method as parameter. This method might be determined at run time only. Not just one method, they can be used to invoke set of methods in a pre-defined order. In simple words, delegates are reference types used to encapsulate methods. This concept is very similar to function pointers in C++ but still there is a major difference between both. Delegates are secure enough and they are object-oriented. But function pointers in C++ lack these two important features.

Delegates are used for many purposes. Most common usage of Delegates is listed below:

• For handling events

• For achieving parallel processing by establishing thread communication

• For defining generic class libraries

• For wrapping and executing a method which can be determined only at run time and not at compile time

• For defining anonymous methods (methods with no name) and executing the method using delegates

• For invoking both static method and instance method using a single delegate

Given below is a simple example for delegates:
public delegate void sampleDelegate(int param1);
public class testDelegate {
public static void testFunc1(int param1) {
console.WriteLine(“The value passed to static method testFunc1 is:{0}”, param1);
}
public void testFunc2(int param1) {
console.WriteLine(“The value passed to instance method testFunc2 is:{0}”, param1);
}
public void testFunc3(int param1, float param2) {
console.WriteLine(“The value passed to instance method testFunc2 is:{0},{1}”, param1,
param2);
}
}
class useDelegate {
public static void Main( ) {
sampleDelegate delegate1 = new sampleDelegate(testDelegate.testFunc1);
delegate1(10);
testDelegate testObj = new testDelegate();
sampleDelegate delegate2 = new sampleDelegate(testObj.testFunc2);
delegate2(20);
sampleDelegate delegate3 = new sampleDelegate(delegate2);
delegate3(30);
}
}

In this example, a delegate called sampleDelegate is declared. Class testDelegate has a static method testFunc1 and an instance method testFunc2. Both these methods have the same signature as that of sampleDelegate. Class useDelegate has Main( ) method that uses sampleDelegate to wrap methods defined in testDelegate class. Inside Main( ) method, an instance of sampleDelegate called delegate1 is wrapping the static method testFunc1 of testDelegate class. Since it is a static method, the method is accessed using the class name. A value is now passed to delegate1 using the code
“delegate1(10);” .
This is equivalent to:
testDelegate.testFunc1(10);

This is what delegation is all about. Method invocation of testFunc1 is delegated to delegate1 and the parameter value is passed to delegate1 instead of testFunc1. Another instance of the delegate called delegate2 is used to wrap the instance method testFunc2.
Since it is an instance method, an instance of testDelegate called testObj is created and testFunc2 is accessed using testObj instead of class name. Other than static and instance methods, delegate can wrap another delegate also. That is shown using delegate3. Note that sampleDelegate cannot be used for wrapping testFunc3 of testDelegate. This is because testFunc3 has a different signature when compared to the signature of sampleDelegate.
In this example three instances of sampleDelegate is used. Each instance is used for calling a different method. Instead of creating individual instances, delegates offer a much more advanced feature known as multicasting. With multicasting, you can create a single instance of sampleDelegate and invoke all the methods matching its signature. Class useDelegate in the above example is further modified as:
class useDelegate {
public static void Main( ) {
sampleDelegate delegateObj = null;
delegateObj = new sampleDelegate(testDelegate.testFunc1);
delegateObj (10);
testDelegate testObj = new testDelegate();
delegateObj += new sampleDelegate(testObj.testFunc2);
delegateObj(20);
delegateObj -= new sampleDelegate(testDelegate.testFunc1);
delegateObj(30);

}
}

In this example, same delegate object is used to execute all methods. Output of this code will be:
The value passed to static method testFunc1 is:10
The value passed to static method testFunc1 is:20
The value passed to instance method testFunc2 is:20
The value passed to instance method testFunc2 is:30

Are you confused by looking at the output? Here’s the justification for the order of execution. Inside Main( ) method an instance of sampleDelegate called delegateObj is created and initialized to null. Then it wraps testDelegate.testFunc1. delegateObj is then invoked with parameter value as 10.
This parameter will now be passed to testDelegate.testFunc1 and the print statement inside the function is executed. To access the instance method of testDelegate class, an instance of the class called testObj is created and the delegateObj wraps the instance method of testDelegate using testObj. But keenly notice that specific line of code. Repeating it here for your reference:
delegateObj += new sampleDelegate(testObj.testFunc2);
See the operator “+=”. This operator appends testObj.testFunc2 inside the delegate along with its earlier method testDelegate.testFunc1. Hence on invoking delegateObj using the statement “delegateObj(20)”, all the methods that are there in the invocation list(in this example testDelegate.testFunc1, testObj.testFunc2) will be executed. Order of execution is same as the order in which methods are appended into the delegate. In the next line of code, yet another operator is used:
delegateObj -= new sampleDelegate(testDelegate.testFunc1);
-= operator is used to remove a method from the invocation list of delegate. As per this example, testDelegate.testFunc1 is removed. Therefore while invoking the delegate, only the method testObj.testFunc2 will be executed.
While performing multicasting, ensure that the return type of the delegate is void. If not, then while invoking the delegate only the return value of the recently added method will be displayed. Return value of all other methods will be lost.

.......................................................................................................................................


Delegates are holding one or multiple function address.The delegate designed using pointers so the delegates are unsafe code from the .Net framework.The delegates are reference types.Depending upon the function prototype we have to declare the delegates.Delegates are of two types

1>Single Cast Delegate.
2>Multi Cast Delegate.

Multi Cast Delegate:
The multi Cast delegate refers multiple single cast delegate.

Example on multicast delegate:

public delegate void dname();
class DelegateDemo
{
public void m1()
{
MessageBox.Show("From m1");
}
public void m2()
{
MessageBox.Show("From m2");
}
}

private void button1_Click(object sender, EventArgs e)
{
DelegateDemo obj = new DelegateDemo();
dname d1 = new dname(obj.m1);
dname d2 = new dname(obj.m2);
dname d3;
d3 = d1 + d2;
d3();
}

0 comments:

Post a Comment