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

C# try-catch-finally 異常處理語句:finally 保證執行機制與資源清理模式

     編輯:關於C語言

核心觀念:finally 的保證

finally 區塊在下列情況**保證執行**:

  • try 正常結束
  • try 中 return/break/continue
  • catch 區塊執行完畢 (含 catch 中 return)
  • catch 區塊重新拋出例外 (throw;)
  • 無匹配 catch,例外向上傳播前

不執行情況:Environment.FailFast、進程被強制終止、無限迴圈、堆疊溢位。

經典範例:無效轉換仍執行 finally

using System;

public class MainClass
{
    static void Main()
    {
        int i = 123;
        string s = "Some string";
        object o = s; // 裝箱

        try
        {
            i = (int)o; // 執行時拋出 InvalidCastException
        }
        catch
        {
            Console.WriteLine("捕獲例外:InvalidCastException");
        }
        finally
        {
            Console.WriteLine($"finally 區塊執行,i = {i}"); // i 保持 123
        }

        Console.WriteLine("程式繼續執行");
        Console.Read();
    }
}

輸出結果

捕獲例外:InvalidCastException
finally 區塊執行,i = 123
程式繼續執行

資源清理模式:檔案、資料庫連線、鎖定

// 模式一:try/finally (C# 1.0 風格)
StreamWriter sw = null;
try
{
    sw = new StreamWriter("data.txt");
    sw.WriteLine("重要資料");
}
finally
{
    if (sw != null) sw.Close(); // 必須檢查 null
}

// 模式二:using 敘述 (C# 2.0+ 推薦,編譯器自動產生 try/finally)
using (var sw = new StreamWriter("data.txt"))
{
    sw.WriteLine("重要資料");
} // 這裡自動呼叫 sw.Dispose() -> Close()

// 模式三:C# 8+ using 宣告 (無大括號)
using var sw = new StreamWriter("data.txt");
sw.WriteLine("重要資料");
// 方法結束自動 Dispose

多重資源清理

// 巢狀 using (C# 8 前)
using (var conn = new SqlConnection(cs))
using (var cmd = conn.CreateCommand())
{
    conn.Open();
    cmd.CommandText = "SELECT * FROM Users";
    using (var reader = cmd.ExecuteReader())
    {
        while (reader.Read()) { /* ... */ }
    }
}

// C# 8+ 扁平化
using var conn = new SqlConnection(cs);
using var cmd = conn.CreateCommand();
conn.Open();
cmd.CommandText = "SELECT * FROM Users";
using var reader = cmd.ExecuteReader();
while (reader.Read()) { /* ... */ }

finally 中的陷阱

陷阱後果解決
finally 中拋出例外遮蔽 try/catch 原始例外finally 僅做清理,不拋出例外
finally 中 return吞沒 try/catch 的 return 值/例外finally 禁止 return
資源未檢查 nullNullReferenceException 掩蓋原錯誤使用 using 或 null 條件運算子
關閉順序錯誤資料遺失、連線洩漏反向順序關閉:Reader → Command → Connection

非同步方法中的 finally

public async Task FetchAsync(string url)
{
    using var client = new HttpClient();
    try
    {
        return await client.GetStringAsync(url);
    }
    catch (HttpRequestException ex)
    {
        Log(ex);
        throw; // 重新拋出
    }
    finally
    {
        // 這裡執行於 await 完成後,client 已在 using 範圍外自動 Dispose
        // 可做額外記錄:Metrics.RecordCompletion();
    }
}

最佳實踐清單

  1. ✅ **優先使用 using** 管理實作 IDisposable 的資源
  2. ✅ finally 僅用於**非受控資源清理**或**不可用 using 的情況**
  3. ✅ finally **不拋出例外、不返回**
  4. ✅ 多重資源按**反向建立順序**清理
  5. ✅ 非同步方法 await 前後皆可用 try/finally,但 using 範圍需涵蓋 await
  6. ✅ 記錄例外時保留 InnerException 與堆疊追蹤
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved