| 屬性 | 說明 |
|---|---|
Message | 異常原因與內容描述 |
Source | 拋出異常的組件名稱 |
StackTrace | 方法呼叫堆疊追蹤 |
InnerException | 包裹的內部異常(鏈結) |
TargetSite | 擲回異常的方法 |
HelpLink | 說明連結 |
Data | 自訂鍵值對資料 |
try
{
// 可能拋出異常的代碼
}
catch (SpecificException ex)
{
// 處理特定異常
}
catch (Exception ex)
{
// 處理其他所有 Exception 衍生異常
}
catch // 不帶參數
{
// 捕獲非 Exception 衍生異常(極罕見,如非託管代碼 SEH)
}
finally
{
// 無論是否發生異常必定執行(資源釋放、清理)
}
catch 與 finally 可選,但至少須有一個。try 可對應多個 catch,但只能有一個 finally。finally 區塊一定會執行(含 return、throw、執行緒中止等情況)。Exception 在後。異常未被捕獲時,沿呼叫堆疊向上傳遞,直到找到匹配 catch 或到達進程入口點。若最終未捕獲,CLR 顯示未處理異常對話框/記錄事件日誌。
throw new ArgumentNullException(nameof(id), "ID 不可為空");
必須是 Exception 或其衍生類型。
catch (Exception ex)
{
Log(ex);
throw; // 保留原始堆疊追蹤
// 錯誤:throw ex; // 會重設堆疊追蹤至當前行
}
System.Exception 或常見基底異常(ArgumentException、InvalidOperationException 等)。Exception 結尾。[Serializable] 支援序列化(跨 AppDomain/遠端)。[Serializable]
public class MyBusinessException : Exception
{
public MyBusinessException() { }
public MyBusinessException(string message) : base(message) { }
public MyBusinessException(string message, Exception inner) : base(message, inner) { }
protected MyBusinessException(SerializationInfo info, StreamingContext context) : base(info, context) { }
// 可選:擴充屬性
public int ErrorCode { get; set; }
public string UserMessage { get; set; }
}
編輯器輸入 Exception 按 Tab Tab 自動產生上述範本。
| 原則 | 說明 |
|---|---|
| 僅捕獲可處理的異常 | 捕獲後無法恢復/記錄/轉換則不應捕獲,讓上層處理 |
| 不要用異常控制流程 | 異常成本高,業務邏輯判斷用 if/return |
| 保留堆疊追蹤 | 重新拋出用 throw; 而非 throw ex; |
| 釋放資源用 using/finally | 確保非記憶體資源(檔案、連線、鎖)釋放 |
| 提供有意義的 Message | 包含足夠上下文資訊供診斷 |
| 區分預期/非預期異常 | 預期異常(驗證失敗)用自定義型別;非預期(Bug)讓它冒泡 |
| 全域未處理異常記錄 | AppDomain.UnhandledException、TaskScheduler.UnobservedTaskException、ASP.NET Core 中介軟體 |
| 異常 | 適用情境 |
|---|---|
ArgumentException | 參數不符合預期(含 ArgumentNullException、ArgumentOutOfRangeException) |
InvalidOperationException | 物件狀態不適合該操作(如集合修改中枚舉) |
NotSupportedException | 不支援的功能 |
NotImplementedException | 尚未實作 |
ObjectDisposedException | 操作已釋放物件 |
TimeoutException | 操作逾時 |
IOException | I/O 錯誤 |