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

.NET 遺忘錄(二):using 區塊——非受控資源釋放的優雅契約

     編輯:關於.NET

.NET 垃圾收集器(GC)僅管理受控記憶體。資料庫連線、檔案控制代碼、GDI 物件、COM 物件等非受控資源,必須由開發者顯式釋放。IDisposable + using 是標準模式,但巢狀 using 與異常安全常被忽略。

演進史:從 try/finally 到 using

// 1. 原始模式:冗長、易漏寫 Close()
SqlConnection conn = new SqlConnection(cs);
conn.Open();
try { ... } finally { if (conn != null) conn.Close(); }

// 2. using 語法糖:編譯器自動展開為 try/finally
using (SqlConnection conn = new SqlConnection(cs)) {
    conn.Open();
    ...
} // 隱含 finally { conn.Dispose(); }

// 3. 多資源巢狀 using:程式碼右移、可讀性下降
using (SqlConnection conn = new SqlConnection(cs)) {
    using (SqlCommand cmd = conn.CreateCommand()) {
        using (SqlDataReader dr = cmd.ExecuteReader()) { ... }
    }
}

巢狀 using 的替代方案:單一 try/finally 多資源

SqlConnection conn = null;
SqlDataReader dr = null;
try {
    conn = new SqlConnection(cs);
    conn.Open();
    SqlCommand cmd = new SqlCommand(sql, conn);
    dr = cmd.ExecuteReader();
    while (dr.Read()) { ... }
}
finally {
    if (dr != null) dr.Dispose();
    if (conn != null) conn.Dispose();
}

優勢:扁平結構、統一錯誤處理、避免 using 隱含的 null 檢查重複(Dispose() 實作應支援多次呼叫)。

SqlDataReader 的特殊陷阱

ExecuteReader() 回傳的 SqlDataReader 持有連線獨佔權。若 CommandBehavior.CloseConnection,關閉 Reader 會自動關閉連線。但在 TransactionScope 環境下,連線由交易管理,**不可**提前關閉,否則後續指令報「Connection is closed」。

最佳實踐清單

  1. 實作 IDisposable 類別**必須**遵循標準 Dispose 模式(含 Dispose(bool)、GC.SuppressFinalize)
  2. 單一資源用 using;多資源同生命週期用單一 try/finally
  3. 非受控資源包裝類別(如 SafeHandle 衍生類)優於手動 IntPtr + DllImport
  4. 異步程式碼使用 await using (C# 8.0+) 或 try/finally 確保 DisposeAsync 執行

結語

using 不只是語法糖,更是資源擁有權轉移的宣告。理解其展開邏輯、巢狀陷阱與交易上下文互動,才能寫出真正健壯的資源管理代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved