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

Effective C# 第 2 章:.NET 資源管理(下)

     編輯:關於C語言

解構函數的效能代價

需解構的物件:

  1. GC 發現為垃圾但有解構函數 → 無法立即回收
  2. 放入解構佇列,由專用終結執行緒執行
  3. GC 繼續清理其他垃圾
  4. 下一輪 GC 才真正回收記憶體

結果:物件在記憶體多存活至少一輪 GC(通常 9+ 輪 Gen 0 收集),甚至晋升到 Gen 2 長期駐留。

代際 GC 機制

  • Gen 0:新建立物件,頻繁收集
  • Gen 1:倖存 1 次 GC 的物件
  • Gen 2:倖存 2+ 次 GC 的物件(大物件堆 LOH 直接進 Gen 2)

有解構函數的物件會延遲代際晋升,增加 GC 壓力。

IDisposable 模式:避免解構函數開銷

public class ResourceHolder : IDisposable
{
    private IntPtr _handle; // 非受控資源
    private bool _disposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); // 關鍵:告訴 GC 不需呼叫 Finalize
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed) return;
        if (disposing)
        {
            // 釋放受控資源
        }
        // 釋放非受控資源
        ReleaseHandle(_handle);
        _handle = IntPtr.Zero;
        _disposed = true;
    }

    ~ResourceHolder() => Dispose(false); // 保底:使用者忘記 Dispose

    [DllImport("kernel32.dll")]
    private static extern bool CloseHandle(IntPtr hObject);
    private void ReleaseHandle(IntPtr h) => CloseHandle(h);
}

using 陳述式:確保釋放

using (var resource = new ResourceHolder())
{
    resource.DoWork();
} // 編譯器產生 try/finally 呼叫 Dispose()

關鍵差異總結

特性解構函數IDisposable + using
時機非確定性(GC 決定)確定性(程式碼控制)
效能差(延遲回收、額外執行緒)優(立即釋放)
適用資源非受控資源保底所有資源(受控+非受控)
例外安全無保證using 保證 finally 執行

最佳實務

  1. 實作 IDisposable 管理所有資源
  2. 解構函數僅作保底(呼叫 Dispose(false))
  3. 永遠用 using 或 try/finally 確保 Dispose()
  4. GC.SuppressFinalize(this) 移除終結佇列登記
  5. 避免在 Dispose 中存取其他終結物件(可能已被終結)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved