当对象超出范围时,事件处理程序会发生什么

本文关键字:程序 什么 事件处理 对象 范围 | 更新日期: 2023-09-27 18:01:08

假设我们有以下设置:

public class ClassA
{
   public event EventHandler SomeEvent;
}
public class ClassB : IDisposable
{
   public void SomeMethod(ClassA value)
   {
      value.SomeEvent += (s, e) => { DoSomething(); };
   }
   void DoSomething() { }
   void Dispose() { }
}
public static class Program
{
   static void Main()
   {
      var a = new ClassA();
      using (var b = new ClassB())
         b.SomeMethod(a);
      // POINT OF QUESTION!!
   }
}

在"问题点"之后引发事件SomeEvent时会发生什么?

当对象超出范围时,事件处理程序会发生什么

它将调用已处理对象的方法。这就是为什么取消订阅很重要。它甚至可能导致内存泄漏。

您应该使用ClassB的Dispose()方法来取消订阅ClassA事件。您会面临类没有被垃圾收集的风险,这当然会导致潜在的内存泄漏。您应该始终取消躲避事件。

上面没有任何东西可以解除事件处理程序的锁定。由于ab同时超出范围,因此您是安全的。由于ab都可以被收集,那么a将不能保持b的存活。

如果在using语句之后引发ClassA.SomeEvent事件,那么即使b已被释放,也会调用ClassB.DoSomething。在这种情况下,您必须显式删除事件处理程序。

如果在其他地方保留对a的引用,那么a将保持b的有效性。同样,因为事件处理程序尚未删除。

什么都没有。Runtime不知道Dispose方法,在使用语句内部调用该方法对内存管理没有任何作用。

垃圾回收是关于内存管理的,但IDisposable(和Finalizer(是关于资源管理的,所以您仍然应该自己思考并手动实现它(并且是有属性的,例如在Dispose中取消订阅(。