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}\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查看委托的更多相关文章
- IL查看泛型
查看泛型的IL 我们在开发中经常用到泛型,下面一起通过IL来查看泛型背后做了那些工作 示例代码 示例代码如下: using System; namespace MyCollection { pub ...
- IL查看override
查看override的IL Override示例 下面我们看一个Override的Example namespace MyCollection { public class MyBase { publ ...
- 30分钟?不需要,轻松读懂IL
先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西.最重要的理由就是一个 ...
- CLR via C#(12)-委托Delegate
本来按照进度应该学习事件了,可总觉得应该委托在前,事件在后,才好理解. 委托是一个类,它提供了回调函数机制,而且是类型安全的.使用委托可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数 ...
- 方法字段[C# 基础知识系列]专题二:委托的本质论
首先声明,我是一个菜鸟.一下文章中出现技术误导情况盖不负责 引言: 上一个专题已和大家分享了我懂得的——C#中为什么须要委托,专题中简略介绍了下委托是什么以及委托简略的应用的,在这个专题中将对委托做进 ...
- 读懂IL
读懂IL 先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西.最重要的理 ...
- .NEL IL实现对象深拷贝
对于深拷贝,通常的方法是将对象进行序列化,然后再反序化成为另一个对象.例如在stackoverflow上有这样的解决办法:https://stackoverflow.com/questions/785 ...
- 【转】.NET IL实现对象深拷贝
对于深拷贝,通常的方法是将对象进行序列化,然后再反序化成为另一个对象.例如在stackoverflow上有这样的解决办法:https://stackoverflow.com/questions/785 ...
- .NET IL实现对象深拷贝
对于深拷贝,通常的方法是将对象进行序列化,然后再反序化成为另一个对象.例如在stackoverflow上有这样的解决办法:https://stackoverflow.com/questions/785 ...
随机推荐
- HTML · 图片热点,网页划区,拼接,表单
图片热点: 规划出图片上的一个区域,可以做出超链接,直接点击图片区域就可以完成跳转的效果. 网页划区: 在一个网页里,规划出一个区域用来展示另一个网页的内容. 网页的拼接: 在一个网络页面内,规划出多 ...
- 使用Apache ab进行压力测试(参数说明)
我们一般会使用Apache自带的ab来对项目进行压力测试,看项目的执行情况如何. 我们可以使用 ab -v 来查看ab的详细参数使用方法. [root@node234 bin]# ./ab -v ab ...
- 硬盘变成RAW的修复过程
可能在不知道为什么的情况下,移动硬盘或者本地磁盘的每个分区变成了RAW格式.其在Win系统下的无损修复过程如下: 用“win”+“R”打开“运行”小窗口: 键入“CMD”: 键入命令“CHKDSK P ...
- 破解 “PEDIY CrackMe 2007” 之 KeygenMe_1_by_boonz
系统 : Windows xp 程序 :KeygenMe_1_by_boonz 程序下载地址 :http://www.crackmes.de/users/boonz/keygenme_1_by_boo ...
- ADB server didn't ACK 解决方法
在安卓开发的过程中 连接真机的时候 连接不上 提示 The connection to adb is down, and a severe error has occured.[2015-01-22 ...
- Mac 以太网连接 报无效的服务器地址 BasicIPv6ValidationError
Mac 以太网连接 报无效的服务器地址 BasicIPv6ValidationError 用Mac这么久,一直是用WiFi连接网络,没搞过以太网连接,我也是醉了 显然 Mac 不能像 Windows ...
- java多线程系列6-阻塞队列
这篇文章将使用经典的生产者消费者的例子来进一步巩固java多线程通信,介绍使用阻塞队列来简化程序 下面是一个经典的生产者消费者的例子: 假设使用缓冲区存储整数,缓冲区的大小是受限制的.缓冲区提供wri ...
- 【读书笔记】iOS-内存管理
Cocoa的内存管理:retain,release和autorelease. 每个对象都维护一个保留计数器.对象被创建时,其保留计数器值为1:对象被保留时,保留计数器值加1:对象被释放时,保留计数器值 ...
- 弃用的异步get和post方法之代理方法
#import "ViewController.h" #import "Header.h" @interface ViewController () <N ...
- Spring(九)Spring对事务的支持
一.对事务的支持 事务:是一组原子操作的工作单元,要么全部成功,要么全部失败 Spring管理事务方式: JDBC编程事务管理:--可以控制到代码中的行 可以清楚的控制事务的边界,事务控制粒度化细(编 ...