| 形式 | 語法 | 說明 |
| 型別捕捉 | catch (ExceptionType ex) | ex 為區域變數,僅在 catch 區塊可見 |
| 型別 + 篩選 | catch (ExceptionType ex) when (condition) | C# 6.0+,條件為 true 才進入 |
| 一般捕捉 | catch 或 catch (Exception ex) | 捕捉所有 CLS 合規例外,必須置於最後 |
| 非 CLS 例外 | catch { } (無參數) | 捕捉非 Exception 衍生例外 (極罕見) |
例外篩選實戰
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) { } 吞噬例外
- 上一篇文章: C# 例外處理機制深度解析:與 C++ 差異、例外傳播與 finally 語意
- 下一篇文章: C# 例外觸發條件:throw 語句與執行時例外條件完整分類
Copyright ©
程式碼之家 All Rights Reserved