我已经读过,引用类型包含对可能存储在托管堆上的实际对象的引用。当一个方法被“赋值”给一个委托引用变量时,该引用指向哪个内存?这个内存块与实际的功能代码有什么关系?
答案 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)
实际上有两种委托类型,Delegate和MulticastDelegate。这些是从delegate
的实际实例继承的抽象类。我建议阅读这些课程,因为他们有比我在这里解释的更多(准确)细节,但是对于短版本:
虽然我并不是100%确定实现的确切方式,但考虑Delegate
对象的最简单方法是保持object
和MethodInfo
,这是反射类型对于特定的方法。 Delegate
类型是抽象的原因是因为Invoke
方法取决于方法的参数。
同样,MulticastDelegate
包含多个Delegate
个对象,每个对象都指向一个单独的object
/ MethodInfo
组合。这允许event
系统,其中单个event
被触发会导致调用多个方法。
回到实现细节,当您定义委托时,它使用MulticastDelegate
方法从Invoke
创建一个继承的类,object
也可以null
为MulticastDelegate
静态方法。
除此之外,你还有{{1}}个对象在调用之间传递的具体细节,但我可能已经在这篇文章中犯过一些错误,所以我会留下它。
答案 2 :(得分:0)
不给出过于复杂的答案,它指向(引用)存储方法的实际内存块。
答案 3 :(得分:0)
委托实际上包含两个地址 - 方法的地址以及对象的地址。这非常有趣,与代表们有关的几项专利被授予Heljsberg http://www.google.com/patents/US6185728
非常高效。在interview中,Heljsberg指出它比VTBL dispatch更有效(因为它是指向函数的直接指针)。在最简单的情况下,它实际上是间接调用。 e.g
jmp *%eax