2009-11-05 75 views
9

我认为委托实例可以与函数实例互换。委托实例和方法指针有什么区别?

看看下面的代码:

delegate int AddDelegate(int a, int b); 

AddDelegate DelegateInstance; 

public void DoStuff() 
{ 
    //I can call this without a delegate "instance": 
    MethodThatTakesAdd(Add); 

    //I can also call it WITH a delegate "instance" 
    DelegateInstance = Add; 
    MethodThatTakesAdd(DelegateInstance); 
} 

public int Add(int a, int b) 
{ 
    return a + b; 
} 

public void MethodThatTakesAdd(AddDelegate addFunction) 
{ 
    Console.WriteLine(addFunction(1, 2).ToString()); 
} 

调用它似乎相当于的两种方式,如果你只使用C#中,你永远不会看到其中的差别(至少我还没有达到这点)。不过,我最近是托管代码的非托管代码,它们的处理方式不同。例如,在一种情况下,如果我直接将该函数用作回调函数(即使我的对象实例保留在附近),我将得到错误“回调是在垃圾回收委托上进行的”。使用“委托实例”可以解决问题。

有没有人知道有什么区别?

+1

il是什么样的?有没有任何迹象表明“底层”,他们通常会被区别对待? – 2009-11-05 16:53:03

回答

13

术语纠正:代替方法指针,更合适的术语是方法组。

就功能而言,两条语句是等价的。那就是他们生产的差不多是的同一个IL。区别在于委托值的存储位置。

在第一种情况传递方法组添加到MethodThatTakesAdd直接。这会导致创建临时委托值,然后传递给MethodThatTakesAdd。这个委托值在MethodThatTakesAdd返回的那一刻进行垃圾回收,因为它不存储该值。

在第二种情况下你分配委托给一个字段在外实例。这将通常增加委托的生命周期,从而减少在您的销售电话期间垃圾收集的机会。

+0

这听起来很合理,并且会解释我所看到的! – 2009-11-05 16:57:43

+0

http://msdn.microsoft.com/en-us/magazine/cc164193.aspx解释了它在“反向的P/Invoke和代表终身”部分 – 2009-11-05 17:32:32

+0

@JaredPar我不明白。这个'AddDelegate DelegateInstance;'是一个委托**实例** ??它只是一个'AddDelegate'类型的变量。代表**实例**将成为myDel + = new MYDEL(myMethod);或myDel + = myMethod;(简称)的**右侧**似乎是合乎逻辑的。 。我错了吗 ? – 2013-05-03 07:52:32

0

虽然代表提供在C#作为在C或C++函数指针同义的功能,也有显著差异。这些中的关键是一个代表是一个类,而不是一个指针。

总之,铸造一个委托的指针是不会给你的功能或方法的引用,因此它不能用于通过从非托管代码参考调用的方法。

4

委托是可调用的类,并具有类似行为到函数指针。委托内部存储要调用的函数的地址(即函数指针),但也提供其他功能,如多播和存储调用列表;你可以使用一个委托实例来调用相同签名的许多函数,如下所示。

public void DoStuff() 
{ 
    DelegateInstance += Add; 
    DelegateInstance += AnotherAdd; 
    DelegateInstance += YetAnotherAdd; 

    // Invoke Add(100, 200), AnotherAdd(100, 200), and YetAnotherAdd(100, 200) 
    DelegateInstance(100, 200); 
} 

关于你关于MethodThatTakesAdd(Add)MethodThatTakesAdd(DelegateInstance), 等价注:如果你看一下MSIL的C#编译器生成行MethodThatTakesAdd(Add),你会发现,编译器创建委托和包装的Add()方法为你。

相关问题