来自Python,我真的很想念Dart的else
连锁店中的try-except
条款。
在Dart中模拟else
条款最惯用的是什么?
这是一个受益于else
块的例子。
这个:
var didFail = false;
try {
startDownload()
} catch (e) {
didFail = true;
downloadFailed()
}
if (!didFail) {
downloadSuccess()
}
afterDownload()
VS:
try {
startDownload()
} catch (e) {
downloadFailed()
} else {
downloadSuccess()
}
afterDownload()
完全披露:我对Dart的整个体验是我刚刚花了2分钟来审查其try
语句的语法。这完全基于对Python语义的观察。
else
在Python中做了什么?跳到建议的Dart代码的答案的末尾。
以下两段代码在Python中非常相似:
try:
...
<last code>
except SomeError:
...
finally:
...
和
try:
...
except SomeError:
...
else:
<last code>
finally:
...
<last code>
将在两个相同的情况下执行。不同之处在于,<last statement>
提出的任何例外都将在第一个中被捕获,但不会在第二个中被捕获。
else
要在Python中模拟else
的语义,您可以使用额外的try
语句和一个标志来指示是否应该重新抛出异常。
else_exception = False
try:
...
try:
<last code>
except Exception as e:
else_exception = True
except SomeError:
...
finally:
if else_exception:
raise e
...
我们检查嵌套的try
是否在finally
子句中捕获了异常,因为else
子句将在finally
之前执行。如果有例外,现在再加注它就不会立即被捕获,就像在else
中一样。然后你可以继续其余的finally
。
else
据我所知,Dart需要相同的逻辑。
bool else_exception = false;
try {
...
try {
<last code>
} catch (e) {
else_exception = true;
}
} on SomeError catch (e) {
...
} finally {
if (else_exception) {
throw e;
}
...
}
请注意,如果<last code>
抛出异常,则上述代码将无法正确保留堆栈跟踪。要做到这一点,需要更多的关注:
bool else_exception = false;
try {
...
try {
<last code>
} catch (e) {
else_exception = true;
rethrow;
}
} on SomeError catch (e) {
if (else_exception) {
rethrow;
}
...
}
在大多数情况下,您应该能够直接在else
块的最末端写入任何进入try
块的内容。可能有some cases块有用的else
,并且可以提供更清晰或更具表现力的代码,但是,例如,您可以编写比您在“其他”示例中所做的更紧凑的代码。
try {
start_download() // exception?
// yay, no exception
download_success()
} catch (e) { // preferrably "on KindOfException catch (e)"
download_failed()
}
afterDownload()
如果没有异常,download_success
只执行它可能不那么明确,但隐含地很明显,因为如果有异常,try
块将被中止并且执行将进入catch
块。
当然,这也意味着在download_success()
提出的例外情况也会转到catch
街区。这可以通过使用更具体的例外来防止,例如, on VeryBadDownloadException catch (e)
,假设start_download
和download_success
不会提出完全相同的异常。