查看委托的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.sql.SQLException: null, message from server: “Host ‘xxx’ is not allowed to connect

    java.sql.SQLException: null, message from server: “Host ‘xxx’ is not allowed to connect 2014年06月29日  ...

  2. 安全协议:SSL、TSL、SSH概述

    SSL(Secure Socket Layer--安全套接字层):为网络通信安全以及数据完整性提供保障的一种安全协议,在TCP/IP的传输层对网络连接进行加密: TSL(Transport Layer ...

  3. R语言归一化处理

    归一化化就是要把你需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内.首先归一化是为了后面数据处理的方便,其次是保正程序运行时收敛加快. R语言中的归一化函数:scale 数据归一化包括 ...

  4. 使用一般处理程序HTTPHandler下载文件

    一般来说我们可以用HTTPHandler来处理一些简单的逻辑,比如验证码.下载文件等. 以下载word文档为例讲解一下如何在HHTPHandler中下载文件,不限于word文档,如果下载其他文件,需要 ...

  5. Oracle_spatial的函数介绍[转]

    Oracle_spatial的函数 一sdo_Geom包的函数: 用于表示两个几何对象的关系(结果为True/False)的函数:RELATE,WITHIN_DISTANCE 验证的函数:VALIDA ...

  6. 安卓开发--android library projects cannot be launched错误

    最新因为学习,问技术友要了几个源代码,导入源代码的时候无法进行真机或者虚拟机测试. 原因:android library projects cannot be launched 百度了一下,解决方法很 ...

  7. 利用UIScrollView实现几个页面的切换

    此实例可以了解一下UIScrollView的运用,以及表格跟页面跳转的内容: 原作者地址:http://www.cocoachina.com/bbs/read.php?tid=323514 效果图如下 ...

  8. 【原】自定义UIPageControl的圆点

    在下面的两种情况下会导致圆点贴图刷新: 1.用户调用setCurrentPage:(NSInteger)currentPage时 所以重载这个函数便可拦截 2.点击圆点矩形区域时     这说明,我们 ...

  9. Android源码分析之Looper

    先来说说summary,Looper就是用来在某个线程中跑一个message loop.一个线程默认是没有message loop与之相关联的, 为了创建一个你必须在这个线程中调用Looper.pre ...

  10. 转 Android中shape中的属性大全

    <shape>            <!-- 实心 -->            <solid android:color="#ff9d77"/&g ...