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

Effective C# 原則 15:使用 using 與 try/finally 進行資源清理(三)

     編輯:關於C語言

多重 using 的嵌套問題與替代方案

每個 using 陳述式產生新的巢狀 try/finally 區塊。我發現這結構不佳,遇到多個實作 IDisposable 的物件時,偏好自寫 try/finally:

public void ExecuteCommand(string connString, string commandString)
{
    SqlConnection myConnection = null;
    SqlCommand MySQLCommand = null;
    try {
        myConnection = new SqlConnection(connString);
        MySQLCommand = new SqlCommand(commandString, myConnection);
        myConnection.Open();
        MySQLCommand.ExecuteNonQuery();
    } finally {
        if (MySQLCommand != null) MySQLCommand.Dispose();
        if (myConnection != null) myConnection.Dispose();
    }
}

(譯註:判斷物件是否為 null 很重要,特別是封裝 COM 的物件,某些釋放是隱式的,重複釋放空物件會拋出例外。例如同一 COM 被兩不同介面變數參考,一個呼叫 Dispose 後另一個會失效。.NET 也需注意,故須判斷 null。)

錯誤的 using 寫法:資源洩漏隱患

請勿自作聰明用 as 寫 using:

// Bad idea. Potential resource leak lurks!
SqlConnection myConnection = new SqlConnection(connString);
SqlCommand MySQLCommand = new SqlCommand(commandString, myConnection);
using (myConnection as IDisposable)
using (MySQLCommand as IDisposable)
{
    myConnection.Open();
    MySQLCommand.ExecuteNonQuery();
}

看似清爽,但有隱蔽 Bug:若 SqlCommand() 建構函式拋出例外,SqlConnection 物件永不會被處理。必須確保每個實作 IDisposable 的物件配置在 using 範圍內或 try/finally 區塊內,否則資源洩漏。

Close() 與 Dispose() 的差異

部分物件同時支援 Dispose 和 Close 釋放資源(如 SqlConnection)。Dispose 釋放更多資源,並呼叫 GC.SuppressFinalize() 告訴 GC 不需解構;Close() 通常不呼叫。結果:物件進入解構佇列,即使解構非必要。有選擇時,Dispose() 優於 Close()(原則 18 詳述)。

重要提醒

  • Dispose() 不從記憶體移除物件,只是釋放非受控資源的 hook。切勿釋放程式其他地方仍在參考的物件。
  • .NET 1500+ 類別中,不到 100 個實作 IDisposable。使用時務必在所有類別中處理:置於 using 或 try/finally,確保每時每刻正確釋放。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved