This article helps you to understand the basics of delegate in .NET Framework.
What is Delegate
During C/C++ time, function pointer was a buzzword using which, you can point to a function and call the pointer in order to invoke the function. In .NET, there is nothing called pointer so .NET comes up with delegate. In one sentence, delegate is a glorified pointer to a function. You can call a static or instance method (function) using traditional classname.methodname or just pointing the method to delegate and call the delegate which, in turn, will call the method.
Delegate provides a mechanism to defining and executing callback. This allows you to define the exact signature of callback and that defines the type of delegate. In general, delegate instance consists of fields like a reference to an object and a pointer to an instance method. However, if the object reference is null, CLR understands it as a static method.
When you declare a delegate, C# compiler generates a classderives from MulticastDelegate. MulticastDelegate contains several methods but you cannot see those methods if you view the IL of your code in ILDASM. It isbecause CLR implements all these methods dynamically at runtime.
Delegate allows classes not to coupled strongly. Also callerof the delegate has no idea whether it is calling a static method or instance method or what exact method it is calling. Think about the GUI Button class.Button class doesn’t know which method it will execute onClick event.
Just think, if we write the code within the button class OnClick event, then wouldit be reusable class? Button class publishes the OnClick event using a delegate and informs that you can subscribe the OnClick event with a method. In this way, you can de-couple your classes using delegate.
How to call Delegate
Before delving into code, you need to understand one very simple rule about delegate. The return-type or parameter list of the method that you want to reference by delegate, should match with delegate type declaration.Confused! Take an example
Suppose I have one method like void PrintToConsole(string message). The delegate type should be delegate void objDelegate(string message).Now if you write objDelegate =PrintToConsole then it is perfect. Call the function using objDelegate(“Hello World”) which will execute the PrintToConsole method.
So what does following statement mean?
public delegate void _delagate(int i,int j);
It means a declaration of delegate that can encapsulate any method which will take two integer parameters and return void.
When you declare above line, C# compiler produces following code snippet
public class NotifyGpaDelegate : System.MulticastDelegate
{
public void Invoke(int GPAScore)
{
// code
}
}
This Invoke method is part of MulticastDelegate and should have the same signature of the defined delegate.
Simple Delegate
public delegate void _MathDelegate(int x,int y);
public class clsMath
{
public void Sum(int i, int j)
{
Console.WriteLine(i + j);
}
public static void Subtract(int i, int j)
{
Console.WriteLine(i – j);
}
}
class Program
{
static void Main(string[] args)
{
clsMath _math = newclsMath();
_MathDelegate _delegate1,_delegate2;
_delegate1 = _math.Sum;
_delegate2 = clsMath.Subtract;
_delegate1(100, 50);
_delegate2(100, 50);
}
}
In the above code, I defined a delegate which return void and take two integer parameters. Since, Iwant to call the Sum/Subtract method using this delegate, you can see I have made them signature compatible between delegate and Sum/Subtract method. In my main method, I defined delegate, reference delegate with the method and callthe delegates, which in turn call the methods. This is an example of simpledelegate.
Delegate Chaining
It means you canmaintain a list of delegates which can be called. Internally it maintains alinked list of delegates and when the head of the list is called, all the delegates in the chain are called. In Delegate class, following methods help toform a delegate chain.
public abstract class Delegate : ICloneable,ISerializable
{
public static Delegate Combine(paramsDelegate[] delegates);
public static Delegate Combine(Delegatea, Delegate b);
}
The first method takes anarray of delegates and return delegate type. You can also remove the delegatefrom delegate chain using following methods defines in Delegate class
public abstract class Delegate : ICloneable, ISerializable
{
public static Delegate Remove(Delegatesource, Delegate value);
public static Delegate RemoveAll(Delegatesource, Delegate value);
}
The source is thedelegate chain and value is the delegate that you want to remove from delegatechain.
In order to makeprogramming simple, C# compiler uses operator overloading to implement thesemethods. You can use + to combine and – to remove from delegate chain.
public delegate void _MathDelegate(int x,int y);
public class clsMath
{
public void Sum(int i, int j)
{
Console.WriteLine(i + j);
}
public static void Subtract(int i, int j)
{
Console.WriteLine(i – j);
}
}
class Program
{
static void Main(string[] args)
{
clsMath _math = newclsMath();
_MathDelegate[] _delegate = new _MathDelegate[]{_math.Sum,clsMath.Subtract};
_MathDelegate _chainDelegate = _delegate[0] +_delegate[1];
_chainDelegate(100, 50);
}
}
In the above example, Idefine one array of delegates which contains all instance and static methods.You can combine those methods using +operator which will call Sum and Subtract method respectively.
_MathDelegate _chainDelegate = _delegate[0] +_delegate[1];
_MathDelegate _chainDelegate1 = _chainDelegate -_delegate[0];
If I use above twostatements, CLR interprets it as (Sum + Subtract) – Sum and execute onlySubtract method. This is an example of removing delegate from delegate chainusing – operator.
You can also iteratethrough the delegate chain.
public delegate int _MathDelegate(int x,int y);
public class clsMath
{
public int Sum(int i, int j)
{
return (i + j);
}
public static int Subtract(int i, int j)
{
return (i – j);
}
}
class Program
{
static void Main(string[] args)
{
int iTemp = 0;
clsMath _math = newclsMath();
_MathDelegate[] _delegate = new _MathDelegate[]{_math.Sum,clsMath.Subtract};
_MathDelegate _chainDelegate = _delegate[0] +_delegate[1];
Delegate[] _delegates =_chainDelegate.GetInvocationList();
for (int i = 0; i< _delegates.Length; i++)
{
_MathDelegate_del = (_MathDelegate)_delegates[i];
iTemp += _del(100, 50);
}
Console.WriteLine(iTemp);
}
}
In the above example, Iused GetInvocationList method to get all the delegates in the delegate chainand call each delegate and summed it up. This method helps us to reference eachdelegate in the delegate chain and we can also call delegate from the delegatechain in any order.
What is MulticastDelegate
A delegate can call more than one method when invoked. Thisis referred to as multicasting. A useful property of delegate objects is thatthey can be assigned to one delegate instance to be multicast 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 toremove a component delegate from a composed delegate. Also multicast delegatereturn type is always void.
We can change the implementation of the above code becauseMulticast Delegate return type should be void.
An Example
class Program
{
// Simple Sum method
public static void Sum(int i, int j)
{
Console.WriteLine(i + j);
}
// Simple Subtract method
public static void Subtract(int i, int j)
{
Console.WriteLine(i – j);
}
// Declaring a simple delegate which will
// encapsulate a Sum/Subtract method
public delegate void _delegate(int x, int y);
static void Main(string[] args)
{
// Declaring objects of Delegate
_delegate objDelegate1, objDelegate2,objDelegate3, objDelegate4;
// Referencing Sum by the delegate object
objDelegate1 = Sum;
// Referencing Subtract by the delegate object
objDelegate2 = Subtract;
// This will call Sum and Subtract both
objDelegate3 = objDelegate1 + objDelegate2;
objDelegate3(100, 50);
// This will call only Subtract
objDelegate4 = objDelegate3 – objDelegate2;
objDelegate4(100, 50);
}
}
objDelegate3 = objDelegate1 + objDelegate2 means it willcall Sum and Subtract method both.
objDelegate4 = objDelegate3 – objDelegate2 means (Sum +Subtract) – Subtract, which means that call to Sum then Subtract and then Sumagain.
No comments:
Post a Comment