2009-08-17 66 views
22

我对C#类及其解构器有点困惑。EventHandlers和C#类析构函数/ Dispose

我要消耗在一个类的实例几个事件处理程序我得到在构造函数中:

public Foo(IFooHandler handler) 
{ 
    handler.Load += Load; 
    handler.Close += Close; 
} 

我需要在Foo类被破坏退订该事件。我是否实施IDisposable,并在那里或解构器中取消订阅?我需要消费那些事件,我不能以另一种方式去做。

对于其中一个类,我创建一个实例,检查进度,然后类实例超出范围。对于另一个,它保留在MainForm中,直到表单关闭。第一个是我担心的事情,因为它可能仍然有对该事件处理程序的引用,并且没有正确执行。

我不想泄漏内存。何时以及如何取消订阅?

回答

24

不要在析构函数中执行它,因为在附加事件处理程序时不会调用它:当您将Foo的实例方法附加为Bar的事件处理程序时,Bar将保存对Foo,所以Foo不会被垃圾收集,其析构函数也不会被调用。

你应该实现IDisposable,和处置你的对象明确

public void Dispose() 
{ 
    if (handler != null) 
    { 
     handler.Load -= Load; 
     handler.Close -= Close; 
    } 
} 
+2

啊!我认为我们不应该实施IDisposable,除非我们正在清理非托管代码? – 2009-08-17 13:08:55

+0

IDisposable可以实现其他原因,它不限于清理非托管资源... – 2009-08-17 13:14:03

+1

如果您看一下常见的一次性模式,有处理托管和非托管资源的路径。大多数情况下,您只有非托管资源和/或托管资源。但是对于你的情况,也可以只管理应该清理的资源。 – Oliver 2009-08-17 13:44:01

3

如果你曾经遇到有A级是一个长期居住类和类(ES)b都是短命的那些订阅事件的问题的A级,那么你可能会对Weak Event Pattern感兴趣。它可能是一个问题,你不会发现是一个,直到它迟到,即Princeton self driving car.