delegate(2)
上一篇我们看了委托的概念和例子,相信很多人都会想,委托是怎么实现的?VS自带的工具ILDASM,可以查看一个exe或者dll文件的IL代码,具体方法是进入Visual Studio Tools 下的 Visual Studio Command Prompt命令行,输入ILDASM就能看到一个可视化的界面,执行File-->Open,可以选择一个exe文件,比如打开上一篇(http://canbeatle.iteye.com/admin/blogs/686138)中的程序生成的exe文件,可以看到这样的结构:
这些内容其实很简单,注意上图中我加的图标的说明,可以看到TestMathClass中的delegate在IL中是一个class,名称为Operation,就是委托的名称,该class拥有4个method,除了构造函数外,分别是BeginInvoke, EndInvoke, Invoke,其中Invoke的签名和delegate的签名是完全一样的,是不是调用委托方法的时候就是执行的Invoke呢?
在我的例子中,委托是在Main函数中赋值和调用的,为了查看具体的实现,我们双击TestMathClass中的Main:void 函数,看看它的具体实现是怎么样的:
.method private hidebysig static void Main() cil managed { .entrypoint // Code size 100 (0x64) .maxstack 3 .locals init ([0] class EventDelegateTest.TestMathClass/Operation operation, [1] int64 sum, [2] int64 product) IL_0000: nop IL_0001: ldnull IL_0002: ldftn int64 EventDelegateTest.MathClass::Add(int32, int32) IL_0008: newobj instance void EventDelegateTest.TestMathClass/Operation::.ctor(object,native int) IL_000d: stloc.0 IL_000e: ldloc.0 IL_000f: ldc.i4.s 11 IL_0011: ldc.i4.s 22 IL_0013: callvirt instance int64 EventDelegateTest.TestMathClass/Operation::Invoke(int32,int32) IL_0018: stloc.1 IL_0019: ldnull IL_001a: ldftn int64 EventDelegateTest.MathClass::Multiply(int32,int32) IL_0020: newobj instance void EventDelegateTest.TestMathClass/Operation::.ctor(object,native int) IL_0025: stloc.0 IL_0026: ldloc.0 IL_0027: ldc.i4.s 30 IL_0029: ldc.i4.s 40 IL_002b: callvirt instance int64 EventDelegateTest.TestMathClass/Operation::Invoke(int32,int32) IL_0030: stloc.2 IL_0031: ldstr "11 + 22 = " IL_0036: ldloc.1 IL_0037: box [mscorlib]System.Int64 IL_003c: call string [mscorlib]System.String::Concat(object, object) IL_0041: call void [mscorlib]System.Console::WriteLine(string) IL_0046: nop IL_0047: ldstr "30 * 40 = " IL_004c: ldloc.2 IL_004d: box [mscorlib]System.Int64 IL_0052: call string [mscorlib]System.String::Concat(object, object) IL_0057: call void [mscorlib]System.Console::WriteLine(string) IL_005c: nop IL_005d: call string [mscorlib]System.Console::ReadLine() IL_0062: pop IL_0063: ret } // end of method TestMathClass::Main
这段IL代码我们不需要全看懂,只需注意这一段(Line15~17):
IL_000f: ldc.i4.s 11 IL_0011: ldc.i4.s 22 IL_0013: callvirt instance int64 EventDelegateTest.TestMathClass/Operation::Invoke(int32,int32)
首先load两个常量(ldc):11和22,然后调用TestMathClass/Operation::Invoke方法。这也证实了刚才的猜想:委托就是一个类,执行的时候就是调用其Invoke方法(BeginInvoke和EndInvoke以后再探讨)。下一篇(http://canbeatle.iteye.com/blog/686800)我将探讨event。