会尝试/最后(没有Catch)冒泡异常吗?

问题描述 投票:0回答:2

我几乎肯定答案是肯定的。如果我使用 Try Final 块但不使用 Catch 块,那么任何异常都会冒泡。正确吗?

对一般实践有什么想法吗?

c# .net vb.net exception
2个回答
155
投票

是的,绝对会的。当然,假设您的

finally
块不会引发异常,在这种情况下,这将有效地“替换”最初引发的异常。


66
投票

对一般实践有什么想法吗?

是的。 小心。当你的finally块正在运行时,它完全有可能正在运行,因为抛出了一个未处理的、意外的异常。这意味着有些东西“坏了”,并且“完全意想不到的事情”可能会发生。 在这种情况下,可以说您根本不应该在finally 块中运行代码。最后块中的代码可能会被构建为假设它所依赖的子系统是健康的,而实际上它们可能会被严重破坏。 finally 块中的代码可能会让事情变得更糟。 比如我经常看到这样的事情:

DisableAccessToTheResource(); try { DoSomethingToTheResource(); } finally { EnableAccessToTheResource(); }

这段代码的作者在想“我正在对世界的状态进行临时突变;我需要将状态恢复到我被调用之前的状态”。但让我们考虑一下所有可能出错的方式。

首先,调用者可能已经禁用了对资源的访问;在这种情况下,此代码可能会过早地重新启用它。

其次,如果 DoSomethingToTheResource 抛出异常,那么启用对资源的访问是否正确?管理资源的代码

意外损坏

。这段代码实际上表示“如果管理代码被破坏,

确保其他代码可以尽快调用该被破坏的代码,这样它也可能会严重失败

”。这似乎是个坏主意。 第三,如果DoSomethingToTheResource抛出异常,那么我们如何知道EnableAccessToTheResource不会也抛出异常?无论资源的使用发生什么糟糕的情况,也可能会影响清理代码,在这种情况下,原始异常将丢失,并且问题将更难诊断。 我倾向于编写这样的代码而不使用 try-finally 块:

bool wasDisabled = IsAccessDisabled(); if (!wasDisabled) DisableAccessToTheResource(); DoSomethingToTheResource(); if (!wasDisabled) EnableAccessToTheResource();

现在,除非需要,否则状态不会发生变化。现在调用者的状态不会被弄乱。现在,如果 DoSomethingToTheResource 失败,那么我们不会重新启用访问。我们假设某些东西已经严重损坏,并且不会冒险尝试继续运行代码而使情况变得更糟。如果可以的话,让来电者处理问题。

那么什么时候运行finally块是个好主意呢?首先,何时会出现异常。例如,您可能认为锁定文件的尝试可能会失败,因为其他人已锁定该文件。在这种情况下,捕获异常并将其报告给用户是有意义的。在这种情况下,关于什么被破坏的不确定性就会减少;清理不太可能让事情变得更糟。

其次,当你要清理的资源是稀缺的系统资源时。例如,在finally 块中关闭文件句柄是有意义的。 (“使用”当然只是编写 try-finally 块的另一种方式。)文件的内容可能已损坏,但现在您对此无能为力。文件句柄最终将被关闭,所以最好早点关闭。

© www.soinside.com 2019 - 2024. All rights reserved.