佔用非受控資源(檔案控制代碼、資料庫連線、GDI+ 物件、COM 物件等)的型別,必須正確釋放資源。.NET 提供標準 Dispose 模式,配合 IDisposable 介面與完成項,確保資源在使用者呼叫 Dispose() 時立即釋放,若使用者忘記,則由完成項在垃圾回收時被動釋放。
Dispose() 釋放受控與非受控資源。~ClassName() 呼叫 Dispose(false),作為最後防線。public class MyResourceHog : IDisposable
{
private bool _alreadyDisposed = false;
~MyResourceHog() => Dispose(false);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool isDisposing)
{
if (_alreadyDisposed) return;
if (isDisposing)
{
// 釋放受控資源
}
// 釋放非受控資源
_alreadyDisposed = true;
}
}
public class DerivedResourceHog : MyResourceHog
{
private bool _disposed = false;
protected override void Dispose(bool isDisposing)
{
if (_disposed) return;
if (isDisposing)
{
// 釋放衍生類受控資源
}
// 釋放衍生類非受控資源
base.Dispose(isDisposing);
_disposed = true;
}
}
Dispose 與完成項絕不可執行除資源釋放外的任何邏輯(如讓物件復活),否則會導致嚴重 Bug。Dispose 與完成項必須支援重複呼叫不拋出例外。IDisposable 成員時才加入完成項;否則僅實作 IDisposable 即可,避免影響衍生類實作標準模式。完成項執行於專用執行緒,物件需多經歷至少一次 GC 週期才能被回收,造成效能負擔。GC.SuppressFinalize(this) 讓主動釋放的物件跳過完成項佇列,提升效能。標準模式同時解決:基類與衍生類各自追蹤釋放狀態、受控/非受控資源分離清理、版本演進時的相容性。