[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);
}
~~~