代理人指的是什么
本文关键字:是什么 代理人 | 更新日期: 2023-09-27 18:25:49
我读到引用类型保存了对实际对象的引用,该对象可能存储在托管堆上。当一个方法被"分配"给委托引用变量时,引用指向什么内存?这个内存块与实际的函数代码有什么关系?
我们来举一个简单的例子:
using System;
class Program
{
delegate bool MyFilter(int x);
bool IsOdd(int x)
{
return x % 2 == 1;
}
static void Main()
{
MyFilter f = new Program().IsOdd;
Console.WriteLine(f(5));
}
}
编译器做什么?让我们从这一行开始:
delegate bool MyFilter(int x);
编译器生成一个类型,看起来有点像:
class MyFilter : MulticastDelegate
{
public MyFilter(Object thisRef, IntPtr method);
public bool Invoke(int x);
// BeginInvoke(), EndInvoke() - Let's ignore those
}
类型MyFilter有一个接受两个参数的构造函数:一个是要调用的方法体的IntPtr,另一个是应该调用此方法的Object。MyFilter类型上的Invoke()方法调用实际的委托。
现在,让我们看看Main()方法中发生了什么。编译器会像这样重写它:
static void Main()
{
MyFilter f = new MyFilter(new Program(), addressof(Program.IsOdd));
Console.WriteLine(f.Invoke(5));
}
当然,addressof不是一个实际的C#运算符,但您可以想象它返回传入方法的主体地址。此外,我没有讨论与委托相关的其他各种主题,如链接(这是MulticastDelegate基类提供的一个功能),但希望我已经解决了您的问题。
总之,委托引用指向一个对象,该对象实现了与委托签名匹配的Invoke方法。该对象跟踪指向需要调用的方法的指针,以及调用该方法的目标对象(除非该方法是静态的)。
实际上有两种委托类型,delegate和MulticastDelegate。这些是从delegate
的实际实例中继承的抽象类。我建议阅读这些课程,因为它们比我在这里解释的要详细得多(准确),但对于简短的版本:
虽然我不能100%确定实现的确切工作方式,但考虑Delegate
对象的最简单方法是持有object
和MethodInfo
,这是特定方法的反射类型。Delegate
类型之所以抽象,是因为Invoke
方法依赖于该方法的参数。
类似地,MulticastDelegate
保存多个Delegate
对象,每个对象指向单个object
/MethodInfo
组合。这允许使用event
系统,其中单个event
被激发会导致多个方法被调用。
回到实现细节,当您定义委托时,它会使用Invoke
方法从MulticastDelegate
创建一个继承类,对于静态方法,object
也可以是null
。
除此之外,您还了解了MulticastDelegate
对象如何在调用之间传递的细节,但我在这篇文章中可能已经犯了一些错误,所以我就到此为止。
在不给出过于复杂的答案的情况下,它指向(引用)存储该方法的实际内存块。
委托实际上包含两个地址——方法的地址和对象的地址。这很有趣,一些与代表相关的专利被授予了Heljsberghttp://www.google.com/patents/US6185728
它是高效的。在一次采访中,Heljsberg指出它可以比VTBL调度更高效(因为它是指向函数的直接指针)。在最简单的情况下,它实际上是一个间接调用。例如
jmp *%eax
总的来说,执行一个委托需要4条指令。