查看委托的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. 动态创建JS

    var element=document.createElement('script'); element.setAttribute('src', './js/move.js'); document. ...

  2. MessageBox的Buttons和三级联动

    一.MessageBox的Buttons MessageBox.Show可以出现有按钮的对话框 例如: DialogResult dr = MessageBox.Show("是否要继续吗?& ...

  3. SharePoint 服务器端对象模型 之 使用LINQ进行数据访问操作(Part 2)

    (四)使用LINQ进行列表查询 在生成实体类之后,就可以利用LINQ的强大查询能力进行SharePoint列表数据的查询了.在传统SharePoint对象模型编程中,需要首先获取网站对象,再进行其他操 ...

  4. Force.com微信开发系列(三)申请测试账号及回复图文消息

    Force.com除了简单的文本消息回复外,还能回复图文并茂的消息.能回复音乐或者视频.能对用户发来的语音进行识别.能够搜集用户的地理位置信息并提供相应的内容或服务等,本文将对这些技能一一展开说明,在 ...

  5. java多线程系列4-线程池

    在之前的文章中,学习了通过实现java.lang.Runnable来定义类,以及像下面这样创建一个线程来运行任务: Runnable task = new TaskClass(task); new T ...

  6. chrome浏览器font-size<12px无效解决办法

    当样式设定font-size<12px时,chrome浏览器里字体显示仍为12px:如font-size:11px; 但是chrome还是12px的大小,很不听话. 今天我就遇到了这样的问题?网 ...

  7. 有用的.NET库

    1. Polly,重试 Polly is a .NET 3.5 / 4.0 / 4.5 / PCL library that allows developers to express transien ...

  8. android JSON解析之JSONObject与GSON

    1.写在前面 JSON数据是android网络开发中常见的数据格式,JSON最常见的传输方法是使用HTTP协议,关于android开发中HTTP协议的使用方法可参考我的另一篇随笔android网络编程 ...

  9. 微信开发(03)之新建按钮时报错 errcode 40054

    在微信开发新建公众号的按钮时,报错如下: {errcode:40054,errmsg:"invalid sub button url domain"} 经过仔细排查,发现是url地 ...

  10. ArcGIS API for JavaScript Beta初步试探(一)

    这段时间一直在看https://developers.arcgis.com/javascript/beta/sample-code/index.html, 下面直接看图片: 叠加了二维arcgis s ...