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

时间:2011-07-05 20:42:35

标签: c# .net events scope

假设我们有以下设置:

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会发生什么?

4 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:1)

上面没有任何东西会解开你的事件处理程序。由于ab同时超出了范围,因此您将是安全的。由于ab都可以收集,因此a不会使b保持活跃状态​​。

如果您在使用声明后提出ClassA.SomeEvent事件,即使ClassB.DoSomething已被处置,也会调用b。在这种情况下,您必须显式删除事件处理程序。

如果您要在其他地方保留对a的引用,那么b将由a保持活跃状态​​。同样,因为事件处理程序尚未被删除。

答案 2 :(得分:0)

您应该使用ClassB的Dispose()方法取消订阅ClassA事件。您冒着不被垃圾收集的风险,这当然会导致潜在的内存泄漏。您应该始终取消发布活动。

答案 3 :(得分:0)

无。运行时不知道Dispose方法,并且在使用语句内部调用此方法不对内存管理执行任何操作。

垃圾收集完全是关于内存管理的,但是IDisposable(和Finalizer)是关于资源管理的,所以你仍然应该自己思考并手动实现它(并且属性,例如在{{中取消订阅) 1}})。