終結器 (~Class()) 由 GC 執行,時機不可控、順序不定、性能開銷大。IDisposable 提供確定性釋放,開發者決定何時清理非托管資源。
public class ResourceHolder : IDisposable
{
private IntPtr _handle; // 非托管資源句柄
private bool _disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // 告訴 GC 無需調用終結器
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// 釋放托管資源(其他 IDisposable 對象)
}
// 釋放非托管資源
if (_handle != IntPtr.Zero)
{
NativeMethods.CloseHandle(_handle);
_handle = IntPtr.Zero;
}
_disposed = true;
}
~ResourceHolder() => Dispose(false); // 保底
}
// 編譯器展開為 try/finally
using (var res = new ResourceHolder())
{
res.DoWork();
}
// 等價於
var res = new ResourceHolder();
try { res.DoWork(); }
finally { if (res != null) res.Dispose(); }
using 保證 Dispose 執行,即使發生異常。IAsyncDisposable / await using。IDisposable 就能阻止 GC → 錯誤,只是提供主動釋放途徑。Dispose 中訪問其他終結器可能已運行的對象 → 風險,遵循 disposing 參數區分。GC.SuppressFinalize → 終結器仍會運行,雙重釋放風險。