Set*_*man 105 .net c# vb.net exception-handling
我几乎肯定答案是肯定的.如果我使用Try Finally块但不使用Catch块,那么任何异常都会冒泡.正确?
一般的做法有什么想法吗?
赛斯
Jon*_*eet 119
是的,绝对会.假设你的finally
块没有抛出异常,当然,在这种情况下,它将有效地"替换"最初抛出的异常.
Eri*_*ert 57
一般的做法有什么想法吗?
是.要小心.当您的finally块正在运行时,它完全可能正在运行,因为已经抛出了未处理的意外异常.这意味着某些东西被打破了,一些完全出乎意料的事情可能会发生.
在那种情况下,可以说你不应该在finally块中运行代码.finally块中的代码可以构建为假设它所依赖的子系统是健康的,而实际上它们可能会被彻底破坏.finally块中的代码可能会使事情变得更糟.
例如,我经常看到这样的事情:
DisableAccessToTheResource();
try
{
DoSomethingToTheResource();
}
finally
{
EnableAccessToTheResource();
}
Run Code Online (Sandbox Code Playgroud)
这段代码的作者正在思考"我正在对世界状态进行临时变异;我需要将状态恢复到我被召唤之前的状态".但是让我们考虑一下这可能出错的所有方法.
首先,调用者已经可以禁止访问资源; 在这种情况下,此代码可能会过早地重新启用它.
其次,如果DoSomethingToTheResource抛出异常,那么启用对资源的访问是正确的做法吗?管理资源的代码意外中断.这段代码说,实际上"如果管理代码被破坏,请确保其他代码可以尽快调用那些损坏的代码,这样它也可能会失败." 这似乎是一个坏主意.
第三,如果DoSomethingToTheResource抛出异常,那么我们怎么知道EnableAccessToTheResource也不会抛出异常?无论可怕的是什么,资源的使用也可能影响清理代码,在这种情况下原始异常将丢失并且问题将更难以诊断.
我倾向于在不使用try-finally块的情况下编写这样的代码:
bool wasDisabled = IsAccessDisabled();
if (!wasDisabled)
DisableAccessToTheResource();
DoSomethingToTheResource();
if (!wasDisabled)
EnableAccessToTheResource();
Run Code Online (Sandbox Code Playgroud)
现在除非需要,否则状态不会发生变异.现在呼叫者的状态并没有被搞乱.现在,如果DoSomethingToTheResource失败,那么我们就不会重新启用访问权限.我们假设某些事情已经被彻底打破,并且不会冒险通过尝试继续运行代码来使情况变得更糟.如果可以,让呼叫者处理问题.
那么什么时候运行finally块是个好主意?首先,当预期异常时.例如,您可能希望锁定文件的尝试可能会失败,因为其他人已将其锁定.在这种情况下,捕获异常并将其报告给用户是有意义的.在这种情况下,减少了什么被打破的不确定性; 你不太可能通过清理让事情变得更糟.
其次,当您正在清理的资源是稀缺的系统资源时.例如,关闭finally块中的文件句柄是有意义的.("使用"当然只是编写try-finally块的另一种方式.)文件的内容可能已损坏,但现在你无能为力.文件句柄最终将被关闭,因此它可能更快而不是更晚.
归档时间: |
|
查看次数: |
29996 次 |
最近记录: |