• IL查看委托


    查看委托的IL

    通过IL来查看委托的原理,

    委托示例代码

    写一个委托的类如下

    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}
    ", 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(); //让屏幕暂停,以方便观察结果
            }
        }
    }

    示例解释

    上面代码比较简单:首先定义了一个包含两个方法的类IntOperations,然后定义了一个委托IntOp,最后用写了一个类MainProgram来演示结果。

    示例运行结果

    image

    查看IL

    通过IL查看这个类的Main方法

    image

    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

    IL解析

    源代码中的“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来认识和使用委托

  • 相关阅读:
    刷题总结——蚯蚓(NOIP2016DAY2T2)
    刷题总结——愤怒的小鸟(NOIPDAY2T3)
    算法复习——高斯消元(ssoi)
    算法复习——高精度集合
    刷题总结——系列维护(ssoi)
    刷题总结——传送带(四川省选)
    算法复习——数位dp(不要62HUD2089)
    算法复习——单调队列(sliding windows,ssoi)
    刷题总结——road(ssoi)
    linux命令学习笔记(61):tree 命令
  • 原文地址:https://www.cnblogs.com/zhaoqingqing/p/3951978.html
Copyright © 2020-2023  润新知