Exception 怎麼丟才丟得準

Debuguy
4 min readAug 2, 2020

Exception Handling 是在寫程式中很常見的工作之一
Exception 處理得好程式出問題的時候 debug 也輕鬆
處理的不好大概就要通靈才能知道程式哪裡出問題

但如果連丟 Exception 都丟不準的話
更不用說後續的 Handling 要怎麼做了

因此這篇想分享的是怎麼丟 Exception 才丟的準
出動茶包射手時才能準確的射中靶心

以下搜集了幾個在過去經驗裡看過的 Exception 處理方式

#1 什麼事都不做

連 try catch 都不寫,讓程式直接 crash 或是跳 Unhandled exception

#2 吃掉 Exception

把 Exception 吃掉之後假裝沒事發生

#3 做些事之後再丟一次 — 版本1

寫個 log 或做一些處理之後再丟一次

#4 做些事之後再丟一次 — 版本2

本質上和 2. 是一樣的但得到的結果可能和你想的不太一樣

舉個例子 🌰

當我們使用 Http 的去請求資料的時候很
有可能遇到各種網路問題而發生 Exception

因此這邊假設當呼叫了 HttpRequest 方法之後
丟出了 TaskCanceledException 的話會發生什麼事?

以上的程式碼就是 #1 什麼都不處理的狀況
因此這個程式會直接終止且在 Console 印出以下訊息

Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
at HowToThrowException.Program.HttpRequest() in Program.cs:line 14
at HowToThrowException.Program.Main(String[] args) in Program.cs:line 9

因此我們可以知道出錯的地方在第 14 行

以上就是 #2 的處理方式,直接吃掉 Exception
像是裝傻一樣
什麼事都沒發生
安然的渡過了一天
這種寫法比 #1 讓程式直接崩潰還要糟
線上在跑的程式如果真的這樣寫很有可能出包的時候
茶包射手也不知道靶在哪
只能通靈了

接下來我們直接比較 #3 #4 的差異

#3 的寫法會得到以下的結果

Oops!
Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
at HowToThrowException.Program.Main(String[] args) in Program.cs:line 15

#4 的寫法會得到以下的結果

Oops!
Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
at HowToThrowException.Program.HttpRequest() in Program.cs:line 21
at HowToThrowException.Program.Main(String[] args) in Program.cs:line 11

由輸出的結果可知
最主要的差異在於

#3 的寫法會以為錯誤發生在第 15 行

Program.cs:line 15

#4 的寫法才能準確的告知錯誤是發生在 21 行

Program.cs:line 21

因此 #3 的寫法其實把之前的 Stack Trace 都吃掉的
這樣會造成往後出錯時 Debug 的困難
#4 的寫法才能完整的保留整個 Stack Trace 紀錄

重點筆記

在 C# 中,若 catch Exception 後
想要再把 Exception 往外丟時
請記得不要在 throw 後面加上 exception

這樣才能保留原本的 Stack Trace 幫助例外發生時
能準確的找到錯誤發生的位置

下一篇文章將介紹如何自訂義具有 Business 意義的 Exception
讓 Exception Handling 更容易處理

並且使用 Inner Exception 的方式保留原本的 Stack Trace
以達到除了增加程式碼在做例外處理時的可讀性外
還是能精準 debug 找出錯誤發生的源頭

傳送門:Exception 怎麼丟才丟得好

--

--