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

C# 設計模式:Safely 方法——優雅處理 Null 返回值的契約式設計

     編輯:關於C語言

前言:為什麼需要 Safely 方法?

在 C# 開發中,我們經常遇到這樣的場景:從集合或管理類中根據鍵值獲取物件。若鍵值不存在,方法回傳 null。調用者若不檢查 null 直接使用,極易拋出 NullReferenceException。為了避免這一問題,調用者往往被迫編寫大量重複的防禦性代碼:

Student student = studentCollection.GetStudentByID("13432");
if (student == null) {
    // 處理 null,拋出異常或記錄日誌
    throw new ArgumentException("學生不存在");
}
// 後續業務邏輯...

這不僅導致代碼冗餘,還違反了「單一職責原則」——調用者不應負責驗證方法契約的有效性。Safely 方法模式應運而生,它通過契約擴展,保證返回非 null 的有效物件,或拋出明確異常,將錯誤處理集中化,簡化調用端邏輯。

核心概念:契約擴展與「適用性」

根據「契約式設計」思想,方法定義是調用者與實現者之間的契約。原方法 GetStudentByID 的後置條件允許返回 null。Safely 方法不修改原方法,而是提供一個擴展契約的新方法(慣例命名為 GetStudentByIDSafely),其契約承諾:

  • 返回的物件一定非 null(即「適用」於當前調用上下文)。
  • 若無法滿足條件,拋出特定異常(如 NotExistedStudentException),而非返回 null。

此處「適用」一詞關鍵:null 本身非無效,只是不適應「調用者假定物件必須存在」的場景。

適用場景

  • 多個調用點依賴方法返回非 null 物件。
  • 無法修改原介面(因其他處仍需原契約)。
  • 調用者不願意或不適合直接處理不適用值,傾向於讓異常向上傳播。

結構與實現

命名慣例:在原方法名後綴 Safely(如 GetXXXSafely)。實現極簡——委託原方法,檢查結果,拋出異常或返回物件:

public Student GetStudentByIDSafely(string sid) 
{
    Student student = GetStudentByID(sid);
    if (student == null)
    {
        throw new NotExistedStudentException(sid); // 自定義異常攜帶上下文信息
    }
    return student;
}

調用端代碼變得乾淨:

// 無需檢查 null,異常由全域處理機制或上層捕獲
Student student = studentManager.GetStudentByIDSafely("13432");
student.EnrollCourse(courseId); // 直接使用

效果與優勢

  1. 消除冗餘:移除調用處重複的 null 檢查與異常拋出代碼。
  2. 統一錯誤語義:拋出領域相關異常(NotExistedStudentException),優於通用的 ArgumentNullException 或 NullReferenceException。
  3. 維護性提升:異常構造邏輯集中在 Safely 方法內,修改錯誤訊息或日誌策略只需改一處。
  4. 契約清晰:方法簽名即文檔,調用者一眼知曉「此方法保證返回有效物件」。

對比:Nullable Object 模式

.NET 2.0 引入 Nullable<T>(即 T?)解決值類型可為 null 問題,而 Nullable Object 模式則為引用類型提供「空物件」實例,統一調用方式(如 ToString() 不拋異常)。兩者差異在於:

  • Safely 方法:強制返回非 null 實體,失敗即拋異常,適合「必須存在」的業務場景。
  • Nullable Object:返回特殊空物件實例,允許統一調用,適合「可選」且需避免 null 檢查的場景。

語言無關性:Safely 模式純屬設計層面,適用於 Java、C++ 等任何支援異常與介面的語言。

總結

Safely 方法是一個輕量級、高收益的慣用模式。它不引入新類型、不改變現有契約,僅通過一個薄封裝層,將「驗證有效性」的責任從調用者轉移到提供者,實現代碼的簡化與語義的明確化。在領域驅動設計中,它更是體現「設計契約」精神的實用技巧。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved