2026-02-03

[C#] 從 try/catch 到 Result Pattern:讓錯誤回到主流程的寫法

最近在整理一段舊系統的商業邏輯時,發現錯誤處理幾乎清一色都是  try/catch + throw

現在其實已經是  21 世紀了,很多時候有更好的方法可以處理 try catch 跟以前學習的方式有點不同

這篇單純記錄我實際套用 Result Pattern 後的想法與最小可行寫法筆記一下..


先講重點結論 - 如果一個失敗是你"早就知道會發生"的狀況,那就不該用 exception 來表達

Result Pattern 的價值不在於多厲害,而是把失敗直接寫進回傳型別,讓控制流程變得在主流程可以得知

不用在外面呼叫也是一堆 try/catch 處理

我常寫的 code:

public User GetUserById(int id) { var user = _repository.Find(id); if (user is null) throw new UserNotFoundException("User is not Existed."); return user; }

這一段程式碼其實沒有錯,只是實務成本太高呼叫端只能被迫去接你的 exception ,其實這資料(用戶)不存在

是一個可以被預期的可能,然後可以被正常表達的處理狀態,就可以調整使用 Result Pattern


Result Pattern 和新想法 ,就是不要用 throw 來中斷流程,而是回傳一個成功或失敗的結果。

於是可以試著把 method 改成這樣

public Result<User> GetUserById(int id){ //... }

這邊給一個比較簡單我也常用的Result<T> 設計

public class Error { public string Message { get; } public Error(string message) { Message = message; } } public class Result<T> { public bool IsSuccess { get; } public T Value { get; } public Error Error { get; } private Result(T value) { IsSuccess = true; Value = value; } private Result(Error error) { IsSuccess = false; Error = error; } public static Result<T> Success(T value) => new(value); public static Result<T> Failure(string message) => new(new Error(message)); }

這樣我們就可以重新實做 GetUserById 

public Result<User> GetUserById(int id) { var user = _repository.Find(id); if (user == null) return Result<User>.Failure("User is not Existed."); return Result<User>.Success(user); } //呼叫方式 var result = service.GetUserById(id); if (!result.IsSuccess) { Console.WriteLine(result.Error.Message); return; } Process(result.Value);


其實看到現在,或許你覺得無聊跟多此一舉,但是其實在實務上你在在設計 API ,我們也會常常使用

Result Pattern 畢竟對方呼叫是 200 正確,但是 service provider 端這邊可能會必須要告訴呼叫端 server 發生出的錯誤

之後這樣的 code 改成 API 也會比較方便,真正的把 try catch 留給我們不能預期的錯誤在去攔截

畢竟以前我常常很喜歡透過各種 Exception 去表示錯誤,我現在幾乎都是 Result + Exception 混用

讓商業邏輯回到 if/else,程式碼會更好讀,也更好測試

等到真的需要錯誤分類或更細緻的錯誤處理時,再慢慢把它補回來就好

在這之前就多打點字,不過現在都有 AI 幫忙寫了,在現在 AI 時代更應該把程式碼寫得更加的結構好維護



--

The bug existed in all possible states. Until I ran the code.

如果這篇文章有幫助到您幫我分享一下,讓我有寫下去的動力...