[TOC]
當程序中出現錯誤時,Dart會使用異常。以下最佳實踐適用于捕獲和拋出異常。
## 避免無on子句的捕獲。
沒有on限定符的catch子句捕獲try塊中代碼拋出的任何內容。Pokemon異常處理很可能不是你想要的。您的代碼是否正確處理StackOverflowError或OutOfMemoryError?如果您錯誤地將錯誤的參數傳遞給該try塊中的方法,您是否希望讓調試器指向您的錯誤,或者您是否愿意接受有用的ArgumentError?你是否希望代碼中的任何assert()語句有效地消失,因為你正在捕獲拋出的AssertionErrors?
答案可能是“不”,在這種情況下,您應該過濾掉捕獲的類型。在大多數情況下,您應該有一個on子句,它限制您了解并且正確處理的運行時故障類型。
在極少數情況下,您可能希望捕獲任何運行時錯誤。這通常是在框架或低級代碼中,它試圖隔離任意應用程序代碼而不會導致問題。即使在這里,捕獲異常通常比捕獲所有類型更好。異常是所有運行時錯誤的基類,并排除了指示代碼中程序錯誤的錯誤。
## 不要在沒有on子句的情況下丟棄捕獲的錯誤。
如果您確實覺得需要捕獲從代碼區域中拋出的所有內容,那么就用捕獲的內容做一些事情。記錄它,顯示它給用戶或重新扔它,但不要默默地丟棄它。
## 拋出只針對編程錯誤實現Error的對象。
Error類是程序錯誤的基類。當拋出該類型的對象或其子接口之一ArgumentError時,這意味著您的代碼中存在一個bug。當您的API想要向調用者報告它正在被錯誤地使用時,拋出一個錯誤會清楚地發送該信號。
相反,如果異常是某種運行時失敗,并不表示代碼中有錯誤,那么拋出錯誤就是誤導。相反,拋出一個核心異常類或其他類型。
## 不要顯式地捕捉Error或實現Error的類型。
從上面可以看出。由于錯誤表明代碼中有錯誤,它應該展開整個callstack,停止程序,并打印堆棧跟蹤,這樣您就可以定位和修復錯誤。
捕捉這些類型的錯誤會破壞這個過程并掩蓋錯誤。與其在事后添加錯誤處理代碼來處理這個異常,不如返回并修復導致它被拋出的代碼。
## 一定要使用rethrow來重新拋出一個捕獲的異常。
如果決定重新拋出異常,最好使用rethrow語句,而不是使用throw拋出相同的異常對象。rethrow保留了異常的原始堆棧跟蹤。另一方面,throw重置堆棧跟蹤到最后拋出的位置。
以下是錯誤示例:
~~~
try {
somethingRisky();
} catch (e) {
if (!canHandle(e)) throw e;
handle(e);
}
~~~
以下是正確示例:
~~~
try {
somethingRisky();
} catch (e) {
if (!canHandle(e)) rethrow;
handle(e);
}
~~~