Most of us quite familiar with the delegate keyword in C#.Delegates provides us with a mechanism to encapsulate a method or multiple methods.These are quite like managed version of function pointers in C#.We normally use delegates to define callback methods.
First we need to define a delegate as a type with it’s signature as shown below.Note here the signature includes both parameters as well as return values.
public delegate void DemoDelegate(int i);
To use the delegate we need define a variable to type DemoDelegate ,instantiate the variable by passing a method name of matching signature and then invoke the delegate by passing suitable parameter values as shown in the snippet below:
class DelegateSample
{
public void ShowDemo()
{
DemoDelegate d = new DemoDelegate(Test); //Create instance
d(10); //Invoke delegate
}
public void Test(int i)
{
Console.WriteLine(“Method Test called with parameter ” + i);
}
}
Now if we take close look into the syntactic details we see all the operation related to delegate closely resembles that of a reference type.So what’s going on inside.On taking a look into the IL code of the assembly we found a new class is generated as shown below:
.class /*02000003*/ public auto ansi sealed DelegateDemo.DemoDelegate
extends [mscorlib/*23000001*/]System.MulticastDelegate/*01000002*/
{
……….
} // end of class DelegateDemo.DemoDelegate
So the C# compiler internally generates a class with the same name as the delegate type and it inherits from a class System.MulticastDelegate.The class System.MulticastDelegate is derived from base class System.Delegate.This method provides two public attributes
- Method – Metadata Method which is getting executed as an instance of System.Reflection.MethodInfo
- Target – Stores the instance on which delegate method executes.
Before we proceed further let us take a quick look into another feature of delegate chaining.Refer to the sample below and refer to the lines marked in red.
class DelegateSample
{
public void ShowDemo()
{
DemoDelegate d1 = new DemoDelegate(Test);
DemoDelegate d2 = new DemoDelegate(Demo);
Console.WriteLine(“Delegate Added”);
DemoDelegate d3 = d1 + d2; //Two delegates are combined
d3(10); //First method Test and then Demo is invoked
Console.WriteLine(“Delegate Removed”);
DemoDelegate d4 = d3 – d1; //One delegate is removed from the combination
d4(10); //Only method Demo is invoked as delegate d1 is removed.
}
public void Demo(int i)
{
Console.WriteLine(“Method Demo called with parameter ” + i);
}
public void Test(int i)
{
Console.WriteLine(“Method Test called with parameter ” + i);
}
What happens when I do + and – operation on delegates.Internally the methods System.Delegate.Combine and System.Delegate.Remove is invoked by the runtime.This we can see in the IL code of the show demo method:
.method public hidebysig instance void ShowDemo() cil managed
{
…………..
IL_0028: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
……………
IL_0049: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class [mscorlib]System.Delegate)
……………..
} // end of method DelegateSample::ShowDemo
Nice article.
Question – if the invocation list of a delegate contains more than 1 entry, then which entry will be pointed by Method and Target properties?
Hi Palash,
Thanx a lot for going through the post.
To answer your question the instance of the combined delegate maintains an private object array _invocationList.This array contains the delegate objects added to the delegate using Combine method.
The Method and Target properties of the combined delegate contains values as per the last entry in _invocationList array.
Yup, then we should always use GetInvocationList() method – right? I dont see any reason to use those two public attributes – Method & Target? Do you?
hi palash,
I think, as the Method and Target properties of the combined delegate contains values as per the last entry in _invocationList array so you dont see any reason to use those public properties.
But when you call the GetInvocationList() method it will return array of Delegates.
Now if you want to check the method and Target information for those methods encapsulated in the multicasting delgate definitely you need to use Method and targrt public peroperties.right?
del is a multicasting delegate.
Delegate[] delegates=del .GetInvocationList ( );
foreach(Delegate dl in delegates)
{
Console .WriteLine ( dl .Method .Name );
Console .WriteLine ( Environment.NewLine);
Console .WriteLine ( dl .Target.ToString());
}