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

throw 關鍵字深度解析:業務驗證、守衛條件、異常傳遞最佳實踐

     編輯:ASP.NET 基礎

核心誤區澄清

throw 不綁定 try-catch。它的唯一職責是「拋出異常對象」,由調用鏈上層決定是否捕獲、如何處理。濫用 try-catch 包裹業務邏輯會導致「異常控制流」反模式。

四大經典使用場景

1. 守衛條件:參數/前置檢查失敗即拋出

public bool ValidateUser(string userName, string password)
{
    if (string.IsNullOrEmpty(userName))
        throw new ArgumentException("值不能為 null 或空白。", nameof(userName));
    if (string.IsNullOrEmpty(password))
        throw new ArgumentException("值不能為 null 或空白。", nameof(password));

    return _provider.ValidateUser(userName, password);
}

特點:快速失敗,保護核心邏輯不被髒數據污染,異常攜帶參數名便於診斷。

2. 業務規則驗證:不可恢復的業務違規

public void PlaceOrder(Order order)
{
    if (order.Items.Count == 0)
        throw new InvalidOperationException("訂單至少包含一個商品。");

    if (order.TotalAmount > _customer.CreditLimit)
        throw new BusinessRuleException("信用額度不足", "CREDIT_LIMIT_EXCEEDED", order.TotalAmount);

    // ... 核心下單邏輯
}

自定義異常攜帶錯誤碼、上下文數據,上層 UI 可友好提示、日誌可精準分析。

3. Switch/模式匹配的默認分支:防禦性編程

public IEnumerable FilterByStatus(IEnumerable source, int statusFlag)
{
    return statusFlag switch
    {
        0 => source.Where(p => p.EndTime > DateTime.Now),      // 進行中
        1 => source.Where(p => p.EndTime <= DateTime.Now),     // 已結束
        2 => source.Where(p => p.IsFeatured),                  // 推薦
        _ => throw new ArgumentOutOfRangeException(nameof(statusFlag), statusFlag, "未知狀態標識")
    };
}

避免「默認靜默忽略」導致數據錯誤難查,新增枚舉值時編譯器會提醒補全分支(若用模式匹配)。

4. 異常轉換與上下文豐富:捕獲底層異常,拋出業務異常

public UserDto GetUserById(int id)
{
    try
    {
        return _repo.GetById(id);
    }
    catch (SqlException ex) when (ex.Number == 2) // 超時
    {
        throw new DataAccessException("數據庫連接超時", "DB_TIMEOUT", ex);
    }
    catch (EntityNotFoundException ex)
    {
        throw new BusinessException($"用戶 {id} 不存在", "USER_NOT_FOUND", ex);
    }
}

使用 when 過濾器精準捕獲,保留原始堆棧(throw; 而非 throw ex;),外層異常攜帶業務語義。

異常類型選擇指南

異常類型適用場景是否預期可捕獲處理
ArgumentException / ArgumentNullException參數驗證失敗否(編程錯誤,應修復代碼)
InvalidOperationException對象狀態不支持當前操作視業務而定
自定義 BusinessException業務規則違規、用戶操作錯誤是(UI 友好提示、記錄審計)
自定義 DataAccessException數據層故障、超時、死鎖是(重試、熔斷、降級)
NotImplementedException接口未實現、功能開發中否(開發期標記)

反模式與避雷

  • catch 後 throw ex:丟失原始堆棧 → catch { throw; } 或 throw new BizEx("msg", ex);
  • 用異常控制正常流程:如 `try { int.Parse(s); } catch { return 0; }` → 用 `int.TryParse`。
  • 吞噬異常:`catch { }` 或 `catch { log.Error(ex); }` 不重新拋出 → 上層以為成功。
  • 在 finally/using 中拋出新異常:掩蓋原始異常 → 收集多異常用 AggregateException 或記錄後再拋。

現代 C# 模式匹配增強

// C# 8+ switch expression 自動覆蓋窮盡性檢查
var result = status switch
{
    OrderStatus.Pending => "待處理",
    OrderStatus.Paid => "已付款",
    OrderStatus.Shipped => "已發貨",
    OrderStatus.Completed => "已完成",
    _ => throw new ArgumentOutOfRangeException(nameof(status), $"未知狀態: {status}")
};
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved