我非常肯定答案是肯定的。如果我使用Try Finally块但不使用Catch块,则任何异常都将冒泡。正确吗?
对于这种做法有什么想法吗?
Seth
没错,它肯定会生效。当然,前提是你的 finally
块不会抛出异常,在这种情况下,它实际上会“替换”最初抛出的异常。
对于这种做法,你有什么想法吗?
有的。一定要小心谨慎。当finally块正在运行时,完全有可能是因为抛出了一个未处理的、意外的异常。这意味着有些东西出了问题,并且可能发生完全意外的事情。
在这种情况下,可以说你根本不应该在finally块中运行代码。finally块中的代码可能被构建为假设其依赖的子系统是健康的,而实际上它们可能已经深度损坏了。finally块中的代码可能会使情况变得更糟。
例如,我经常看到这种情况:
DisableAccessToTheResource();
try
{
DoSomethingToTheResource();
}
finally
{
EnableAccessToTheResource();
}
这段代码的作者在想:“我对世界状态做了一次临时变更,需要将状态恢复到调用之前的状态。” 但是让我们来思考一下可能会发生什么问题。
首先,资源访问可能已被调用方禁用;在这种情况下,该代码重新启用它,可能过早地启用。
其次,如果DoSomethingToTheResource抛出异常,那么启用资源访问是正确的吗?管理资源的代码意外破坏了。实际上,该代码的含义是“如果管理代码出错,请确保其他代码尽快调用该错误代码,以便使其也彻底失败”。这似乎不是一个好主意。
第三,如果DoSomethingToTheResource抛出异常,那么我们怎么知道EnableAccessToTheResource也不会抛出异常呢?任何困扰使用资源的可怕情况也可能影响清理代码,在这种情况下,原始异常将丢失,问题将更难以诊断。
我倾向于编写不使用try-finally块的代码:
bool wasDisabled = IsAccessDisabled();
if (!wasDisabled)
DisableAccessToTheResource();
DoSomethingToTheResource();
if (!wasDisabled)
EnableAccessToTheResource();
现在状态只有在必要时才会被更改。现在,调用者的状态不会被搞乱。如果DoSomethingToTheResource失败,我们现在不会重新启用访问权限。我们假设存在严重问题,不冒试图继续运行代码而使情况更糟的风险。如果可能的话,由调用方解决这个问题。