實作 IDisposable 做成兩件事:提供及時釋放所有受控資源的機制;提供標準模式讓使用者釋放非受控資源。這很重要:實作後,使用者可避免解構損失,你的類別成為 .NET 社區表現良好的成員。
如何讓衍生類別清理自身資源,同時基類也能妥善清理?(譯註:呼叫 Dispose 時必須呼叫基類 Dispose。但前面說只有一個旗標標識是否已處理,不管先呼叫哪個,總有一個方法無法處理旗標,存在隱患。)若基類重載解構函式或實作 IDisposable,這些方法必須呼叫基類方法;否則基類無法妥善釋放資源。解構與處理共享相同職責:幾乎肯定你複製了解構與處理方法間的程式碼。重載介面方法不如預期運作(原則 26)。標準 Dispose 模式第三個方法:透過受保護虛擬輔助函式,製造共同任務並掛接衍生類別釋放資源。基類包含介面核心程式碼,衍生類別提供 Dispose() 虛擬函式或解構函式負責清理:
protected virtual void Dispose(bool isDisposing);
重載方法同時完成解構與處理必須任務,且為虛擬函式,為所有衍生類別提供入口。衍生類別可重載此函式,提供恰當實作釋放自身資源,並呼叫基類函式。isDisposing 為 true 時可同時清理受控與非受控資源;為 false 時只能清理非受控資源。兩種情況都可呼叫基類 Dispose(bool) 讓它清理自身資源。
public class MyResourceHog : IDisposable
{
private bool _alreadyDisposed = false;
~MyResourceHog() { Dispose(false); }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true);
}
protected virtual void Dispose(bool isDisposing)
{
if (_alreadyDisposed) return;
if (isDisposing) { /* free managed resources */ }
/* free unmanaged resources */
_alreadyDisposed = true;
}
}