查看委托的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}\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(); //让屏幕暂停,以方便观察结果

        }

    }

}

示例解释

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

示例运行结果

查看IL

通过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

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来认识和使用委托

IL查看委托的更多相关文章

  1. IL查看泛型

    查看泛型的IL 我们在开发中经常用到泛型,下面一起通过IL来查看泛型背后做了那些工作 示例代码 示例代码如下: using System;   namespace MyCollection { pub ...

  2. IL查看override

    查看override的IL Override示例 下面我们看一个Override的Example namespace MyCollection { public class MyBase { publ ...

  3. 30分钟?不需要,轻松读懂IL

    先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西.最重要的理由就是一个 ...

  4. CLR via C#(12)-委托Delegate

    本来按照进度应该学习事件了,可总觉得应该委托在前,事件在后,才好理解. 委托是一个类,它提供了回调函数机制,而且是类型安全的.使用委托可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数 ...

  5. 方法字段[C# 基础知识系列]专题二:委托的本质论

    首先声明,我是一个菜鸟.一下文章中出现技术误导情况盖不负责 引言: 上一个专题已和大家分享了我懂得的——C#中为什么须要委托,专题中简略介绍了下委托是什么以及委托简略的应用的,在这个专题中将对委托做进 ...

  6. 读懂IL

    读懂IL 先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西.最重要的理 ...

  7. .NEL IL实现对象深拷贝

    对于深拷贝,通常的方法是将对象进行序列化,然后再反序化成为另一个对象.例如在stackoverflow上有这样的解决办法:https://stackoverflow.com/questions/785 ...

  8. 【转】.NET IL实现对象深拷贝

    对于深拷贝,通常的方法是将对象进行序列化,然后再反序化成为另一个对象.例如在stackoverflow上有这样的解决办法:https://stackoverflow.com/questions/785 ...

  9. .NET IL实现对象深拷贝

    对于深拷贝,通常的方法是将对象进行序列化,然后再反序化成为另一个对象.例如在stackoverflow上有这样的解决办法:https://stackoverflow.com/questions/785 ...

随机推荐

  1. 写给java程序员的c++与java实现的一些重要细微差别

    0.其实常规的逻辑判断结构.工具类.文件读写.控制台读写这些的关系都不大,熟悉之后,这些都是灵活运用的问题. 学习c/c++需要预先知道的一个前提就是,虽然有ANSI C标准,但是每个c/c++编译器 ...

  2. C# Out 传值

    public void Out(out int a, out int b) {//out相当于return返回值 //可以返回多个值 //拿过来变量名的时候,里面默认为空值 a=1; b=2; } s ...

  3. django使用笔记

    django的具体使用可以看官方手册http://djangobook.py3k.cn,这里主要记录使用django中遇到的问题. 1.中文编码问题. 因为我们用到的东西基本上都有中文,在settin ...

  4. ResponsiveSlides.js 幻灯片实例演示

    在线实例 默认效果 导航和分页 缩略图 描述说明 回调函数 <div class="wrap">     <ul class="rslides" ...

  5. [js开源组件开发]图片放大镜

    图片放大镜 一般情况下,手机由于屏幕太小,会有图片上看不清的问题,所以我就做了一个放大镜的js效果,支持pc和移动端.它的原理是利用的backgroundsize来实现的,所以你的浏览器首先要支持这个 ...

  6. SAP技术相关Tcode

    ABAP的常用tcode 开发----------------------------------------------- SE51  屏幕制作 SE91  MESSAGE OBJECT SE80  ...

  7. atitit.mp4 视频文件多媒体格式结构详解

    atitit.mp4 视频文件多媒体格式结构详解 1. 一.基本概念1 2. MP4文件概述2 3. mp4是由一个个“box”组成的,2 4. 典型简化mp43 5. Fragments5 6. r ...

  8. Android使用layer-list实现三面边框

    layer-list可以将多个图片或形状按照顺序层叠起来 <?xml version="1.0" encoding="utf-8"?> <la ...

  9. 苹果手机不进post方法

    今天遇到一个问题,开发的公众号中的一个界面在安卓和微信开发者工具中可以正常显示,在苹果手机中加载不出数据. 以下是部分代码: var start = 0; var limit = 15; var ca ...

  10. jhljx跑跑跑(找规律)

    题目来源:https://biancheng.love/contest/41/problem/D/index jhljx跑跑跑 题目描述 数学不好的jhljx又在和别人打牌,他们一共m人每人n张牌,牌 ...