代表指出了什么?

时间:2012-02-25 03:48:24

标签: c# .net delegates

我已经读过,引用类型包含对可能存储在托管堆上的实际对象的引用。当一个方法被“赋值”给一个委托引用变量时,该引用指向哪个内存?这个内存块与实际的功能代码有什么关系?

4 个答案:

答案 0 :(得分:14)

让我们分开一个简单的例子:

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方法的对象。该对象跟踪指向需要调用的方法的指针,以及调用该方法的目标对象(除非该方法是静态的)。

答案 1 :(得分:0)

实际上有两种委托类型,DelegateMulticastDelegate。这些是从delegate的实际实例继承的抽象类。我建议阅读这些课程,因为他们有比我在这里解释的更多(准确)细节,但是对于短版本:

虽然我并不是100%确定实现的确切方式,但考虑Delegate对象的最简单方法是保持objectMethodInfo,这是反射类型对于特定的方法。 Delegate类型是抽象的原因是因为Invoke方法取决于方法的参数。

同样,MulticastDelegate包含多个Delegate个对象,每个对象都指向一个单独的object / MethodInfo组合。这允许event系统,其中单个event被触发会导致调用多个方法。

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

除此之外,你还有{{1}}个对象在调用之间传递的具体细节,但我可能已经在这篇文章中犯过一些错误,所以我会留下它。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

委托实际上包含两个地址 - 方法的地址以及对象的地址。这非常有趣,与代表们有关的几项专利被授予Heljsberg http://www.google.com/patents/US6185728

非常高效。在interview中,Heljsberg指出它比VTBL dispatch更有效(因为它是指向函数的直接指针)。在最简单的情况下,它实际上是间接调用。 e.g

 jmp *%eax

总体而言,需要4 instructions to execute a delegate