标签:des style blog http color os io 使用 ar
通过IL来查看委托的原理,写一个委托的类如下:
这段代码结构比较简单:首先定义了一个包含两个方法的类IntOperations,然后定义了一个委托IntOp,最后用写了一个类MainProgram来演示结果。
using System;namespace MyCollection{    //定义一个类,该类包含两个静态方法    class IntOperations     {        //求整数的倍数public void Twice(int num)
        {            Console.WriteLine("整数{0}的倍数是 {1}", num, num * 2);}
        //求整数的平方public static void Square(int num)
        {            Console.WriteLine("整数{0}的平方是 {1}\n", num, num * num);}
}
delegate void IntOp(int x); //定义一个委托
public class DelegateExample
    {static void Main(string[] args)
        {            //实例化一个IntOperations对象            IntOperations mo = new IntOperations();            //创建Twice方法的委托对象            IntOp operations = new IntOp(mo.Twice);            //创建并增加Square方法的委托对象            operations += new IntOp(IntOperations.Square);operations(5);
operations(8);
            //创建并移除Square方法的委托对象            operations -= new IntOp(IntOperations.Square);operations(5);
operations(8);
            Console.WriteLine("按任意键退出...");            Console.ReadLine(); //让屏幕暂停,以方便观察结果}
}
}
运行结果如上图所示
通过IL查看这个类的Main方法
IL代码如下:
.method private hidebysig static void Main(string[] args) cil managed
{.entrypoint
  // Code size       118 (0x76).maxstack 3
  .locals init ([0] class MyCollection.IntOperations mo,           [1] class MyCollection.IntOp operations)IL_0000: nop
  IL_0001:  newobj     instance void MyCollection.IntOperations::.ctor()IL_0006: stloc.0
IL_0007: ldloc.0
  IL_0008:  ldftn      instance void MyCollection.IntOperations::Twice(int32)IL_000e: newobj instance void MyCollection.IntOp::.ctor(object,
                                                               native int)IL_0013: stloc.1
IL_0014: ldloc.1
IL_0015: ldnull
  IL_0016:  ldftn      void MyCollection.IntOperations::Square(int32)IL_001c: newobj instance void MyCollection.IntOp::.ctor(object,
                                                               native int)//将一个委托对象组合到一个委托链中IL_0021: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
                                                                                          class [mscorlib]System.Delegate)IL_0026: castclass MyCollection.IntOp
IL_002b: stloc.1
IL_002c: ldloc.1
IL_002d: ldc.i4.5
//执行方法  IL_002e:  callvirt   instance void MyCollection.IntOp::Invoke(int32)IL_0033: nop
IL_0034: ldloc.1
IL_0035: ldc.i4.8
  IL_0036:  callvirt   instance void MyCollection.IntOp::Invoke(int32)IL_003b: nop
IL_003c: ldloc.1
IL_003d: ldnull
  IL_003e:  ldftn      void MyCollection.IntOperations::Square(int32)IL_0044: newobj instance void MyCollection.IntOp::.ctor(object,
                                                               native int)//从委托链上移除找到的委托对象IL_0049: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
                                                                                         class [mscorlib]System.Delegate)IL_004e: castclass MyCollection.IntOp
IL_0053: stloc.1
IL_0054: ldloc.1
IL_0055: ldc.i4.5
  IL_0056:  callvirt   instance void MyCollection.IntOp::Invoke(int32)IL_005b: nop
IL_005c: ldloc.1
IL_005d: ldc.i4.8
  IL_005e:  callvirt   instance void MyCollection.IntOp::Invoke(int32)IL_0063: nop
  IL_0064:  ldstr      bytearray (09 63 FB 4E 0F 61 2E 95 00 90 FA 51 2E 00 2E 00   // .c.N.a.....Q....                                  2E 00 )                                           // ..IL_0069: call void [mscorlib]System.Console::WriteLine(string)
IL_006e: nop
  IL_006f:  call       string [mscorlib]System.Console::ReadLine()IL_0074: pop
IL_0075: ret
} // end of method DelegateExample::Main
源代码中的“operations+=new IntOp(IntOperations.Square);”对应于IL代码中的IL_0021行,就是调用System.Delegate类的 Combine方法,它将一个委托对象组合到一个委托链中去(关于委托链请参见:参考文献1的P377页),委托链上增加了方法Square。不过只有相 同类型的委托才可以组合。
同理,“operations-=new IntOp(IntOperations.Square);”对应于代码IL_0049行,调用System.Delegate类的Remove方法从委 托链上移除找到的委托对象。
当然,如果把委托链上所有的方法都移出去,那么委托就没有可以调用的方法。这个时候如果你在引用这个委托的话那么肯定不能通过编译,因为编译器没有方法可以处理对象。
如果从类的角度考虑委托,那么就会容易理解一些。当然,如果你不用ILdasm反汇编一下,就看不到背后的秘密了。
所以,蔡学镛说:.Net程序员可以不会用IL Assembly写程序,但是至少要看得懂反汇编出来的IL Assembly Code。
推荐一篇好文章:通过IL来认识和使用委托
标签:des style blog http color os io 使用 ar
原文地址:http://www.cnblogs.com/zhaoqingqing/p/3951978.html