C# 3.0 引入的擴展方法不僅能為已編譯的型別增加新功能,若能結合泛型與型別推斷,更能大幅減少重複代碼、提升復用性。本文透過實例示範如何以擴展方法統一處理空值驗證,並提供預設實例建立機制,讓程式碼更簡潔、安全。
假設資料存取層有個方法依角色名稱查詢客戶:
public IEnumerable<Customer> FindCustomers(string roleName) {
return from customer in context.Customer
where customer.RoleName.Equals(roleName)
select customer;
}
若呼叫端直接鏈式取第一筆:
Customer customer = new CustomerDAL().FindCustomers(Role.Admin).First();
當查無資料回傳 null 時,即會拋出 NullReferenceException。傳統做法是在方法內部判斷並拋出自訂例外或回傳空集合,但這會導致驗證邏輯散落各處,難以維護。
OrThrow 擴展方法Craig Andera 提出利用擴展方法將驗證邏輯抽離:
public static T OrThrow<T>(this T obj, Exception e) {
if (obj == null) { throw e; }
return obj;
}
呼叫端即可寫成:
Customer customer = new CustomerDAL()
.FindCustomers(Role.Admin)
.OrThrow(new MyException("Can't find Customer"))
.First();
優點:
Instance 擴展方法自動建立預設實例若不想拋出例外,而是想在 null 時自動建立空實例,可定義:
public static T Instance<T>(this T obj) where T : new() {
if (obj == null) { obj = new T(); }
return obj;
}
注意 where T : new() 約束,故無法用於 IEnumerable 等介面,但對具體類別(如 List<string>)極為有效:
public class ListObject {
public List<string> Foo() { return null; }
}
// 安全取得 Count,若為 null 則自動 new List<string>(),印出 0
Console.WriteLine(new ListObject().Foo().Instance().Count);
擴展方法不只是語法糖,善用泛型與型別推斷,能將橫切關注點(如空值驗證、預設建立)集中化,減少樣板代碼,提升專案可維護性。下次遇到重複的 if (x == null) 判斷,不妨考慮寫個擴展方法統一處理。