2009-08-17 32 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.