csharp-error-handlinglisted
Install: claude install-skill CloudyWing/ai-dotfiles
# C# 例外處理規範
## 例外設計原則(Crucial)
### 何時拋出例外
例外用於表達**程式無法繼續正常流程**的狀況,不用於控制流程。
```csharp
// ❌ 錯誤:用例外控制流程
try {
Order order = GetOrder(id);
Process(order);
} catch (OrderNotFoundException) {
return NotFound();
}
// ✅ 正確:可預期的失敗用回傳值處理
Order? order = FindOrder(id);
if (order is null) {
return NotFound();
}
Process(order);
```
### 例外類型選用
| 例外類型 | 適用情境 |
| --- | --- |
| `ArgumentNullException` | 參數為 null |
| `ArgumentException` | 參數值不合法(非 null 但不符規則) |
| `ArgumentOutOfRangeException` | 參數超出允許範圍 |
| `InvalidOperationException` | 物件狀態不允許目前操作 |
| `NotSupportedException` | 介面方法在此實作中不支援 |
| `KeyNotFoundException` | 以鍵查詢但不存在 |
| `FormatException` | 字串格式不符預期 |
- 可預期的業務錯誤(如「餘額不足」「庫存不足」):依專案慣例,使用自訂例外或 Result Pattern,不使用 `Exception` 基底類別。
- **禁止** `throw new Exception("...")`(太籠統,呼叫端無法精確捕捉)。
### 自訂例外
```csharp
// ✅ 正確:繼承最接近語意的例外類別
public class InsufficientBalanceException : InvalidOperationException {
public InsufficientBalanceException(decimal required, decimal available)
: base($"餘額不足:需要 {required},可用 {available}。") {
Required = required;
Available = available;
}
public decimal Required { get; }
public decimal Available { get; }
}
```
- 自訂例外命名以 `Exception` 結尾。
- 攜帶與錯誤直接相關的結構化資料(如上例的 `Required`、`Available`),方便呼叫端判斷處理。
## Guard Clause(Crucial)
方法入口處優先驗證前置條件,驗證失敗立即拋出例外,避免巢狀 if-else。
### 內建 Guard 方法(.NET 6+)
```csharp
public void CreateOrder(string customerName, int quantity) {
ArgumentException.ThrowIfNullOrWhiteSpace(cu