声明一下,我来自 Java 背景,不怎么用 C#。这两个世界之间有许多共通之处,但当然也存在差异,其中一个就是对异常的思考方式。
最近我回答了一个 C# 问题,建议在某些情况下这样做是合理的:
try {
some work
} catch (Exeption e) {
commonExceptionHandler();
}
我得到了一个回复,但我不太理解:
直到.NET 4.0之前,捕获异常非常糟糕。这意味着你会捕获各种低级致命错误,并掩盖错误。这还意味着,在触发此类异常的某种损坏事件中,堆栈上任何打开的finally块都将被执行,因此即使调用callExceptionReporter()函数尝试记录并退出,它可能甚至无法到达该点(finally块可能会再次抛出异常,或者引起更多损坏,或从磁盘或数据库中删除重要内容)。
也许我比我意识到的更加困惑,但我不同意其中的一些观点,请其他人给出评论。
我知道有很多低级别的异常我们不想忽略。我的commonExceptionHandler()函数可以合理地重新抛出这些异常。这似乎与这个问题的答案一致。它说“根据您的上下文,使用catch(...)可以是可接受的,前提是重新抛出异常。”因此,我得出结论:使用catch(Exception)并不总是有问题,只是在某些情况下悄悄地忽略某些异常是不好的。
短语“直到.NET 4之前,捕获异常非常糟糕”是什么意思?.NET 4中发生了什么变化?这是指AggregateException吗?它可能使我们能够对我们捕获的异常做一些新的事情,但我认为并没有改变基本的“不要忽略”规则。
接下来的短语真的让我不安。这可能正确吗?
这也意味着,在触发此类异常的某种损坏事件中,堆栈上任何打开的finally块都将被执行(finally块可能会再次抛出异常,或者引起更多损坏,或从磁盘或数据库中删除重要内容)。
我理解如果某些低级别的代码有:
lowLevelMethod() {
try {
lowestLevelMethod();
} finally {
some really important stuff
}
}
在我的代码中,我调用了lowLevel();
try {
lowLevel()
} catch (Exception e) {
exception handling and maybe rethrowing
}
无论我是否捕获异常,这都不会对finally块的执行产生任何影响。在我们离开lowLevelMethod()时,finally已经运行了。如果finally要执行任何糟糕的事情,比如损坏我的磁盘,那么它就会执行。我的捕获异常没有任何作用。如果它到达我的异常块,我需要做正确的事情,但我不能是未能执行finally块的原因。