事件处理程序的匿名方法不是泄漏?

noc*_*ura 2 .net c#

每当您向事件处理程序添加委托时,您应该稍后将其删除,对吧?因此,如果您将匿名方法附加到事件,这是否会创建事件处理程序泄漏,因为您以后无法将其删除?来自http://msdn.microsoft.com/en-us/library/0yw3tz5k%28VS.80%29.aspx的代码示例似乎暗示这是一个好的做法.

// Create a handler for a click event
button1.Click += delegate(System.Object o, System.EventArgs e)
                   { System.Windows.Forms.MessageBox.Show("Click!"); };
Run Code Online (Sandbox Code Playgroud)

这真的是一个好的做法吗?

Jon*_*eet 10

每当您向事件处理程序添加委托时,您应该稍后将其删除,对吧?

不一定,没有.通常,您希望事件处理程序在事件本身可以被引发时保持有效 - 这在UI中肯定非常常见.

这真的是一个好的做法吗?

当然,只要你不需要解开处理程序.想想你解开事件处理程序的那一点.如果它是"当表单(或按钮,或其他什么)可以用于垃圾收集时"那么删除处理程序有什么好处?只是让它与表单垃圾收集......


Ser*_*rvy 6

每当您向事件处理程序添加委托时,您应该稍后将其删除,对吧?

好吧,并非总是如此.您要删除要添加的事件处理程序有两个原因:

  1. 您经常将处理程序添加到短暂的同一实例中.如果你没有删除它们,那么当不需要大多数处理程序时,会添加越来越多的处理程序.
  2. 你的处理器的内部保存到一个对象谁的寿命比无论什么对象的事件属于寿命短得多的引用,事件处理程序将不会(或不能)调用一次,其他对象超出范围.留下附着要么迫使它留在记忆长于所需,或可能导致使用对象是"过时",不应该再使用事件处理程序.(例如,如果资源已被处置,则您不希望再触发该事件.)

#2的原因是因为垃圾收集在C#中的工作原理.这标志着,它可以是100%的所有对象确定在范围为"活着",然后遵循任何那些"活着"的对象引用作为也直到它遵循每个活动对象的每个引用是"活着"的一切.任何从未被标记为"活着"的东西都被认为是"死",并且有资格进行垃圾收集.

如果事件处理程序附加到委托包含两件事的事件,则该对象的实例和在该对象上运行的方法.在以下情况之前,引用的对象将无法进行垃圾回收:

  1. 事件的对象不再"活着".
  2. 您删除了您的委托的事件处理程序(即引用),允许您的对象更早被释放.

也就是说,很大一部分案例不适用于其中任何一个案例,因此无需费心去除事件处理程序.

作为一个例子,我经常看到人们在事件对象超出范围之前删除事件处理程序.那是毫无意义的.如果对象超出范围,那么保持对...的引用没有问题.

现在,如果您处于需要取消订阅事件处理程序的少数情况之一,并且您正在使用匿名方法,则需要...不是.只需创建一个可以使其成为命名方法并使用它的类.