2010-01-13 52 views
8

我有以下類使用IDisposable取消訂閱事件 - 我是否需要將其他內容放在處置中?

public class Presenter: IDisposable 
{ 
    public IView View 
    {get;private set;} 

    //snip other object reference, all managed 
    public Presenter(IView view) 
    { 
    View=view; 
    View.MouseUp += MouseUpEvent; 
    } 

    public void MouseUpEvent() 
    { 
    //do whatever you want to do on mouse up 
    } 

    public void Dispose() 
    { 
    View.MouseUp -= MouseUpEvent; 
    // no more manual disposing 
    } 
} 

現在的問題是,我是不是正確地貫徹執行Dispose()方法?或者我需要手動處理所有其他管理對象,因爲我已經明確定義了Dispose()

我認爲即使沒有我手動操作,GC也足夠智能地自行處理(事件訂閱除外)。我對嗎?

回答

8

如果您在構造函數中訂閱的選擇去的話,這看起來是合理的。我會迴應喬希的觀點,認爲這可能不是最好的方法。另一方面,它可能是實現你的目標的最簡單的方式,這總是一件好事。我不會假裝成爲UI模式的專家:提出了關注,我會假設這是你想要工作的方式,並且解決這個問題本身:)

我個人發現喬希的處方模式對於簡單場景過於複雜 - 您的方法很好,只需進行一次更改:讓您的課程密封起來。如果你不想想要封印課程,你應該去Dispose(bool)選項(但沒有終結者),因爲子類可能還需要處理東西,並且可能需要終結器。沒有衍生類型的可能性,生活就更簡單了(因爲它經常是這樣)。

不需要因爲您現在執行IDiposable需要爲其他成員做任何事情。

那麼,你需要從這個類中進一步推導出來嗎?


我不明白,這是推薦標準模式,雖然我建議您更詳細閱讀Joe Duffy et al意見 - 它都可以得到非常複雜。

+0

我不認爲我需要它。我接受了你對愛因斯坦的回答,因爲我發現你更容易理解(不是每個凡人都能理解愛因斯坦:))。 – Graviton 2010-01-13 07:23:05

+0

即使你沒有專門持有非託管資源,因爲一個子類可能是,而且它不應該是不受限制的,這是我的理解,如果類不是密封的,你應該*有一個終結器(就像Component的情況一樣)必須知道基類是否負責在定稿時調用Dispose(bool)。但就像我說過我正在談論話題。 – Josh 2010-01-13 07:49:26

+0

@Josh:我相信如果你需要在你的類中使用終結器,你應該實現一個並調用Dispose(false)'。無論如何,'Dispose'應該可以多次調用。這比擁有不必要的終結器的類加載要好。終結者現在應該很少見(使用SafeHandle等),但他們有一個真正的性能成本。 – 2010-01-13 08:42:55

5

就我個人而言,我會避免在構造函數中鉤住/解除事件並處理。相反,我會將代碼添加到View get/set訪問器並將其添加到那裏。但是,如果Presenter在處理視圖時處理,我不打算試圖清理它。如果您需要明確的分離,您可以明確地從演示者分離視圖。

說了這麼多,以下是我對IDisposable的瞭解。

推薦使用implementing IDisposable的方法是在受保護的Dispose(bool)方法中執行操作。原因是,你想要一個明確的處理和由定稿處置區分(垃圾收集。)

當你被配置,因爲明確的Dispose()調用的,它的確定摸管理對象和你預計將處置您創建的任何需要處置的內容。所以你只有在處置= true時才這樣做。

但是,如果某人(你)忘記調用Dispose並且調用了終結器,那麼在垃圾回收之後(disposing = false)將會丟棄它,並且您不想觸摸任何受管對象,因爲它們可能已經完成。在這種情況下,您唯一需要釋放的就是Win32句柄等非託管資源。

最後,當顯式調用Dispose()時,您會注意到我調用了GC.SupressFinalize(this),它是垃圾收集器的性能提示。它讓它知道該對象在收集時不需要完成。定稿並不便宜。

class MyObject : IDisposable { 

    ~MyObject() { 
     Dispose(false); 
    } 

    public void Dispose() { 
     Dispose(true); 
     GC.SupressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) { 
     if (disposing) { 
      // dispose of managed resources 
     } 
     // dispose of unmanaged resources 
    } 

} 
+3

你不想添加終結器('〜MyObject(){Dispose(false);}'),除非你的類擁有非託管資源。在這種情況下,最好將非託管資源句柄包裝在「SafeHandle」中。一般來說,實現'IDisposable'的設計良好的對象要麼來自'CriticalFinalizerObject',要麼不會有終結器。 – 2010-01-13 06:52:36

+0

關於終結者的很好的一點。 – Josh 2010-01-13 06:56:15

相關問題