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

本文关键字:在内部 方法 类型 | 更新日期: 2023-09-27 18:06:25

我知道委托类型继承自MulticastDelegate,而MulticastDelegate又继承自delegate类。

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

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

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

如果你在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所期望的模式,然后就这样了。委托的实际工作方式取决于运行时。

比如说,我们有一个这样的委托:

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接口。