委托实例和方法指针之间有什么区别?

我认为委托实例可以与函数实例互换。

请使用以下代码:

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()); } 

两种方式称它为APPEAR是等价的,如果你只使用C#,你将永远不会看到差异(至少我还没有达到这一点)。 但是,我最近是一个回调到这个托管代码的非托管代码,它们被区别对待。 例如,在一个场景中,如果我直接使用函数作为回调(即使我的对象实例被保留),我也会得到错误“对垃圾收集的委托进行了回调”。 使用“委托实例”可以解决问题。

那里有人知道有什么区别吗?

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

在function方面,这两个陈述是等价的。 那就是他们产生几乎相同的IL。 不同之处在于存储委托值的位置。

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

在第二种情况下,您将委托分配给外部实例上的字段。 这通常会增加委托的生命周期,从而减少在pinvoke调用期间收集垃圾的机会。

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

 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)的等价性的注释,如果你看一下C#编译器为MethodThatTakesAdd(Add)行生成的MSIL,你会注意到编译器正在创建一个委托并包装Add()方法给你。

虽然委托提供C#中的同义function作为C或C ++中的函数指针,但存在显着差异。 其中的关键是委托是一个类 ,而不是指针。

简而言之,将委托转换为指针不会为您提供对函数或方法的引用,因此它不能用于通过非托管代码的引用来调用方法。