代理人指的是什么

本文关键字:是什么 代理人 | 更新日期: 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对象的最简单方法是持有objectMethodInfo,这是特定方法的反射类型。Delegate类型之所以抽象,是因为Invoke方法依赖于该方法的参数。

类似地,MulticastDelegate保存多个Delegate对象,每个对象指向单个object/MethodInfo组合。这允许使用event系统,其中单个event被激发会导致多个方法被调用。

回到实现细节,当您定义委托时,它会使用Invoke方法从MulticastDelegate创建一个继承类,对于静态方法,object也可以是null

除此之外,您还了解了MulticastDelegate对象如何在调用之间传递的细节,但我在这篇文章中可能已经犯了一些错误,所以我就到此为止。

在不给出过于复杂的答案的情况下,它指向(引用)存储该方法的实际内存块。

委托实际上包含两个地址——方法的地址和对象的地址。这很有趣,一些与代表相关的专利被授予了Heljsberghttp://www.google.com/patents/US6185728

它是高效的。在一次采访中,Heljsberg指出它可以比VTBL调度更高效(因为它是指向函数的直接指针)。在最简单的情况下,它实际上是一个间接调用。例如

 jmp *%eax

总的来说,执行一个委托需要4条指令。