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

C# 例外處理實戰:try-catch-finally 結構、例外篩選與資源清理模式

     編輯:關於C#

throw 陳述式兩種形式


// 1. 拋出新例外
throw new ArgumentException("參數無效", nameof(param));

// 2. 重新拋出當前例外 (僅在 catch 區塊合法)
catch (Exception ex)
{
    Log(ex);
    throw; // 保留原始堆疊追蹤
    // throw ex; // 錯誤:重置堆疊,切勿使用
}

try 區塊三種完整形式


// Form 1: try-catch
try { Risky(); }
catch (IOException ex) { Handle(ex); }

// Form 2: try-finally
try { Acquire(); }
finally { Release(); }

// Form 3: try-catch-finally
try { Transact(); }
catch (SqlException ex) { Rollback(); throw; }
finally { CloseConnection(); }

catch 子句詳細規則

例外篩選實戰


try
{
    ProcessFile(path);
}
catch (IOException ex) when (ex.HResult == -2147024864) // FILE_NOT_FOUND
{
    CreateDefaultFile(path);
}
catch (IOException ex) when (ex.HResult == -2147024891) // ACCESS_DENIED
{
    LogSecurityAudit(path);
    throw;
}
catch (IOException ex)
{
    // 其他 IO 錯誤
    throw;
}

篩選器不進入 catch 區塊,不會展開堆疊,有利於偵錯保留原始現場。

一般捕捉與重新拋出模式


try
{
    LegacyInteropCall(); // 可能拋出非 CLS 例外
}
catch (Exception ex) when (false) // 永不捕捉,僅為了偵錯中斷點
{
    // 永不執行
}
catch // 一般捕捉:捕捉所有 (含非 CLS)
{
    // 記錄、清理
    throw; // 重新拋出原例外 (保留型別與堆疊)
}

finally 區塊核心語意

  • 保證執行:正常結束、return、break、continue、goto、例外傳播
  • 執行順序:內層 finally → 外層 finally → catch (外層)
  • 例外遮蔽:若 finally 拋出例外,原傳播例外遺失

try
{
    try { throw new Exception("Inner"); }
    finally { Console.WriteLine("Inner finally"); throw new Exception("From finally"); }
}
catch (Exception ex)
{
    Console.WriteLine($"Caught: {ex.Message}"); // Caught: From finally
}
// 原始 "Inner" 例外遺失!

資源清理最佳模式

模式 1:using (推薦)


using (var conn = new SqlConnection(cs))
using (var cmd = conn.CreateCommand())
{
    conn.Open();
    return cmd.ExecuteScalar();
}

模式 2:try-finally 手動釋放


SqlConnection conn = null;
try
{
    conn = new SqlConnection(cs);
    conn.Open();
    // ...
}
finally
{
    conn?.Dispose(); // C# 6.0+ null 條件運算子
}

模式 3:自訂資源類別實作 IDisposable


public class TransactionScope : IDisposable
{
    private bool _completed;
    public void Complete() => _completed = true;
    
    public void Dispose()
    {
        if (!_completed) Rollback();
        ReleaseResources();
    }
}

// 使用
using (var tx = new TransactionScope())
{
    DoWork();
    tx.Complete(); // 不呼叫則 Dispose 時 Rollback
}

實戰範例:安全計算平方根差值


double x = 3, y = 4;
double z;
try
{
    z = Math.Sqrt(x * x - y * y); // 可能負數 → NaN 或例外
}
catch (ArithmeticException)
{
    z = Math.Sqrt(y * y - x * x); // 交換順序
}
finally
{
    z += 1.0; // 統一後處理
}
Console.WriteLine(z);

總結檢查清單

  • [ ] 具體例外在前,一般例外在後
  • [ ] 使用 when 篩選避免不必要捕捉
  • [ ] catch 區塊:記錄、復原、重新拋出 (throw) 或轉譯包裝
  • [ ] finally:只做清理,不拋出例外、不返回值
  • [ ] 實作 IDisposable 配合 using 取代手動 try-finally
  • [ ] 避免 catch (Exception) { } 吞噬例外
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
形式語法說明
型別捕捉catch (ExceptionType ex)ex 為區域變數,僅在 catch 區塊可見
型別 + 篩選catch (ExceptionType ex) when (condition)C# 6.0+,條件為 true 才進入
一般捕捉catch 或 catch (Exception ex)捕捉所有 CLS 合規例外,必須置於最後
非 CLS 例外catch { } (無參數)捕捉非 Exception 衍生例外 (極罕見)