2012-05-17 64 views
4

我有下面的類:WinForms和處置自定義控件

public class NewListBox : ListBox 
    { 
     public NewListBox() 
     { 
     } 

     private ImageList _myImageList; 

     public ImageList ImageList 
     { 
      get { return _myImageList; } 
      set { _myImageList = value; } 
     } 
    } 

我很感興趣,是否這個對象的處置將觸發處置對象的字段,如將ImageList的,或者我應該實現(重寫)Dispose方法並自己完成這項工作?

回答

5

您應該將ImageList添加到您的控件的Components集合中,然後Dispose的基類實現將Dispose集合中的所有內容,並且您不必重寫Dispose。

如果您有任何成員是IDisposable,但不是組件,那麼您將不得不在控件中重寫Dispose並自行處理它們。我使用嚴格意義上來自System.ComponentModel.Component的對象的Component這個術語。

+2

是否有一致的模式,其WinForms控件採取了IDisposable性質的所有權,哪些沒有?我的理解是,通過類似'Image'屬性(控件通常不擁有的東西)的代碼,將控件的「Image」屬性設置爲該控件之外無需用途的圖片的代碼也應該附加到該控件的Disposed事件,並在控件處於Dispose時處理Dispose,但並非所有屬性都以這種方式工作。 'Font'屬性看起來很奇怪...... – supercat

+2

...因爲我們將一個控件的Font屬性設置爲一個已經處理好的字體,並且控件不會介意。我不知道這是一個好還是壞的想法,但它似乎工作。 – supercat

5

article是非常有用的,在內存處置部分。

所有實現IDisposable的類(包括所有的Windows窗體控件)都有一個Dispose方法。當不再需要對象來釋放內存以外的資源時,必須調用此方法。有兩種方式發生這種情況:

    手動
  • (通過調用處置明確)
  • 自動:通過將對象到.NET容器,如一種形式,面板,或TabPage的用戶控件 。集裝箱將確保它在處置時,它的所有成員也一樣。當然,容器本身必須被處置(或者反過來,成爲另一個容器的一部分)。 在Windows窗體控件的情況下,我們幾乎總是將它們添加到容器中 - 因此依賴於自動處理。
1

這裏不同的答案地塊..

我強烈建議閱讀Garbage Collector Basics and Performance Hints 在你萬一你兩個可選:

  • 手動處置ImageList中,所以的ressource將被釋放 快速(但不是立即)
  • 什麼都不做:資源將在下次發佈垃圾 收集器分析您所在的世代。如果你的表格是 已關閉,並且沒有任何內容保留對你的表格的引用,那麼你的表格 將被丟棄,然後因爲沒有引用將指向 ImageList,ImageList將被丟棄。資源 將被釋放,但比第一種情況晚一點。

除非你有大的圖像千元在你的ImageList(或者,如果你創建/關閉窗體次百),你會不會注意到基於代碼2例

+0

GC與我所問的內容無關。當某個類代表或持有本地資源(該ImageList可能包含,我不確定)時,它需要妥善處置。 GC查找對象根目錄(哪些對象仍然可以訪問)並收集那些無法再訪問的對象。這並不意味着這些對象是「Disposed」(意味着它們所持有的資源將被正確釋放)。我的問題是關於WinForms,以及我是否可以通過表單本身自動處理我的對象。 –

+0

GC調用對象和開發人員的Finalize方法調用Dispose方法。兩者都與釋放資源有關,這是由GC完成的。所以是的,你的問題與GC有關。如果ImageList處理原生資源,他的工作是通過實現Finalize方法來釋放它(這是因爲ImageList從Component繼承而來)。開發人員可以通過調用dispose方法加速實現,但如果不這樣做,則不會發生內存泄漏。 – Fabske

0

之間有什麼區別你已經發布了,你沒有使用Designer來實現這個控件。因此,您不會有設計師提供的Dispose(bool disposing)方法或System.CompononetModel.IContainer components成員,您可以將其額外控制添加到該成員。我不知道ListBox如何處理它的Controls屬性,但是如果它允許您在那裏註冊您的ImageList實例,那麼應該會自動獲得Dispose()行爲。

你的另一個選擇是覆蓋Control.Dispose(bool)類似如下:

protected override void Dispose(bool disposing) 
{ 
    // Only call Dispose() on members if invoked through a direct 
    // call to `Dispose()`. (If disposing is false, that means 
    // we are invoked through the finalizer and we should *only* 
    // free up unmanaged resources that we *directly* own). 
    if (disposing) 
    { 
     ImageList.Dispose(); 
    } 

    base.Dispose(disposing); 
} 
相關問題