C#移除事件处理程序

28

我已经做了一段时间,但我没有注意到每次删除事件处理程序时都在使用 new。我是否应该创建一个新对象?

基本上,1 和 2 有什么区别?

  1. ethernetdevice.PcapOnPacketArrival -= new SharpPcap.PacketArrivalEvent(ArrivalResponseHandler);

  2. ethernetdevice.PcapOnPacketArrival -= ArrivalResponseHandler;

编辑: 好的,这是一个重复的问题。抱歉。 答案发布在这里

具有相同目标、方法和调用列表的同一类型的两个委托被认为是相等的。

2个回答

32

在语法上,1和2没有区别,因为2是1的简化写法。只有当2指向一个类级委托实例字段而不是实际方法名称时,编译生成的IL代码才会有所区别。

就运行时而言,在传递给Add方法和Remove方法的委托实例是否相同方面,Remove方法似乎并不关心。我不记得这是为什么了,但我猜测委托实例总是被合并在一起。

编辑:Jon Skeet称,事件Remove方法使用值相等性(Delegate.Equals)来确定从列表中删除哪个委托实例,而不是合并+引用相等性。结果相同,方法不同。 :-)


由于委托只是一个方法和(可选的)实例的引用,因此比较这两个应该足以确定相等性。 - Botz3000
是的,但一般来说,如果在任意引用类型上两次调用new T(),您将获得两个不同的实例。由于委托似乎不是这种情况,我推断委托构造函数自动对实例进行了内部处理,就像Type类所做的那样。 - Christian Hayter
3
@Christian:不,它没有对任何内容进行实例化处理- 它只是使用Delegate.Equals,这个方法会比较委托的方法和目标。 - Jon Skeet
2
实习是指在创建新实例之前检查是否已存在具有相同值的现有实例。如果存在这样的实例,则返回该实例。这确保了内存中只存在类型的唯一实例。例如,字符串始终在编译时进行实习,但除非手动调用String.Intern,否则不会在运行时进行实习。 - Christian Hayter
今天学到了新东西。谢谢Christian! - Sharun
显示剩余2条评论

13

第二个版本与第一个版本等效; 它只是使用了更短的语法。 这是在C# 2.0 中实现的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接