Archive for November 29, 2008

Delegates in C#

Posted: November 29, 2008 in .NET
Tags: ,

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

  1. Method – Metadata Method which is getting executed as an instance of System.Reflection.MethodInfo
  2. 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