首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 內存管理深度解析(九):IDisposable 模式與 using 塊

     編輯:關於C語言

為什麼需要 IDisposable?

終結器 (~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); // 保底
}

using 塊語法糖


// 編譯器展開為 try/finally
using (var res = new ResourceHolder())
{
    res.DoWork();
}
// 等價於
var res = new ResourceHolder();
try { res.DoWork(); }
finally { if (res != null) res.Dispose(); }

最佳實踐

  • 封裝非托管資源:文件句柄、數據庫連接、Socket、GDI+ 對象、COM 對象。
  • 密封類無需 virtual Dispose:簡化為非虛擬方法。
  • 異常安全:using 保證 Dispose 執行,即使發生異常。
  • 異步資源:.NET Core 3.0+ 支持 IAsyncDisposable / await using。

常見誤區

  1. 以為實現 IDisposable 就能阻止 GC → 錯誤,只是提供主動釋放途徑。
  2. 在 Dispose 中訪問其他終結器可能已運行的對象 → 風險,遵循 disposing 參數區分。
  3. 忘記 GC.SuppressFinalize → 終結器仍會運行,雙重釋放風險。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved