如何在内部生成委托类型的方法?

时间:2011-08-22 17:11:58

标签: c# delegates

我知道委托类型是从MulticastDelegate继承的,而MulticastDelegate又继承自Delegate类。

当我们创建委托实例时,它会创建三个方法(Invoke,BeginInvoke,EndInvoke,除了构造函数),并具有相同的委托签名。

我无法理解它是如何在内部创建的(具有委托类型签名的方法)?

提前致谢。

2 个答案:

答案 0 :(得分:4)

如果你看一下Reflector或ILSpy中委托类型的IL,你会发现它看起来像这样:

.class public sealed System.Action extends System.MulticastDelegate
{
    .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed {}

    .method public hidebysig newslot virtual instance void Invoke() runtime managed {}

    .method public hidebysig newslot virtual instance class System.IAsyncResult BeginInvoke(class System.AsyncCallback callback, object 'object') runtime managed {}

    .method public hidebysig newslot virtual instance void EndInvoke(class System.IAsyncResult result) runtime managed {}
}

即构造函数(.ctor),InvokeBeginInvoke/EndInvoke方法。您还会注意到这些方法没有实现(方法体是空的),并标有runtime

runtime关键字向CLR指示此方法需要CLR本身提供的实现。也就是说,委托的实现完全是在CLR本身内部的Magic。加载委托类型时,CLR会注意到它派生自System.Delegate,注意到runtime标志,因此在CLR中为该特定委托类型创建了这些方法的实现。

这些实现实际上看起来完全取决于您运行它的CLR(无论是.NET平台,Mono还是其他),但可能直接使用本机代码。

当编译器编译委托类型时,它只是创建这些方法存根以匹配CLR所期望的这种模式,并将其留在那里。委托的实际工作方式取决于运行时。

答案 1 :(得分:2)

让我们举例来说,我们有一个像这样的代表:

public delegate int BinaryOp(int x, int y);

编译器如何知道如何定义Invoke(),BeginInvoke()和 EndInvoke()方法?

这是编译器生成的类:

sealed class BinaryOp : System.MulticastDelegate
{
public BinaryOp(object target, uint functionAddress);
public int Invoke(int x, int y);
public IAsyncResult BeginInvoke(int x, int y,AsyncCallback cb, object state);
public int EndInvoke(IAsyncResult result);
}

首先,请注意为Invoke()方法准确定义的参数和返回值 匹配BinaryOp委托的定义。

BeginInvoke()成员的初始参数(在我们的例子中是两个整数)也基于BinaryOp委托;
但是,BeginInvoke()将始终提供两个用于促进异步方法调用的最终参数(类型为AsyncCallback和object)。

最后,EndInvoke()的返回值与原始值相同 委托声明,并始终将实现该声明的对象作为唯一参数 IAsyncResult接口。