實作 IDisposable 的型別,呼叫端有責任呼叫 Dispose() 釋放非受控資源。若遺漏,資源將拖到完成項執行時才被動釋放,延長物件存活時間、降低效能。C# 提供 using 與 try/finally 兩種保證機制。
// 編譯器轉換為 try/finally
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand(sql, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
}
// 相當於:
SqlConnection conn = null;
try
{
conn = new SqlConnection(connStr);
SqlCommand cmd = null;
try
{
cmd = new SqlCommand(sql, conn);
conn.Open();
cmd.ExecuteNonQuery();
}
finally { if (cmd != null) cmd.Dispose(); }
}
finally { if (conn != null) conn.Dispose(); }
巢狀 using 產生巢狀 try/finally,IL 膨脹。多資源時,手寫單一 try/finally 更清晰:
SqlConnection conn = null;
SqlCommand cmd = null;
try
{
conn = new SqlConnection(connStr);
cmd = new SqlCommand(sql, conn);
conn.Open();
cmd.ExecuteNonQuery();
}
finally
{
if (cmd != null) cmd.Dispose();
if (conn != null) conn.Dispose();
}
注意:null 檢查必要,避免重複釋放或 COM 封裝物件二次釋放失敗。
// 錯誤:若 SqlCommand 建構失敗,conn 永不被釋放
using (conn as IDisposable)
using (cmd as IDisposable) { ... }
原則:實作 IDisposable 的物件必須在建構時直接置入 using 範圍或 try 區塊。
SqlConnection 同時提供 Dispose() 與 Close()。Dispose() 釋放更多資源並呼叫 GC.SuppressFinalize(),讓物件跳過完成項佇列;Close() 通常不抑制完成項。有選擇時優先呼叫 Dispose()。
Dispose() 不會從記憶體移除物件,僅釋放非受控資源。IDisposable;用到時務必用 using 或 try/finally 正確處理。