考虑以下C#代码结构(S0-S3是任意代码块的占位符):
try
{
S0;
}
catch (Exception ex)
{
S1;
}
finally
{
S2;
}
S3;
如果S1在
catch
处理程序内引发异常,则finally
内的S2仍将执行(但S3不会)。问题
假设S1不能抛出,那么将S2放在
finally
块中,而不是将其放在try/catch/final之外(就在S3之前),有什么意义吗?例子
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
finally
{
S2;
}
S3;
拥有
finally
块有什么意义吗?以下代码是否等效(严格假设catch
块中的内容不能抛出):try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
// No finally block needed (?)
S2;
S3;
次要问题
更新:如果接受以上两个代码块等效(在陈述的假设下),那么考虑到答案中有关代码清晰度的反馈,将S2和S3合并在内部是可取的(等效)吗?
finally
块?try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
finally
{
S2; // Put S2 and S3 together inside the `finally` block to guard against
S3; // future changes in the `catch` filter, or handling code.
}
最佳答案
考虑到资源耗尽的情况(即内存用完),S1无法抛出的假设是一个脆弱的假设。即使有保证(如果有保证的话),对代码的微小更改也会引入异常。
由于S2通常与清理和释放宝贵的资源有关,因此将其放在finally块中可以清楚地传达意图。在可能的情况下,将这样的代码放在资源拥有对象的Dispose()方法中,并用using子句替换try/finally子句,可以更好地传达意图(对于C#来说更惯用)。
只要您可以用两种或更多种不同的方式写东西,就使用最清晰,最稳定的方式来应对变化。
关于第二个问题:如果涉及到清理,则应将S3放置在finally内。如果它以try块的成功为前提,则应将其放置在finally块之后。如果您的catch语句没有被抛出,我个人将其解释为您已经成功并且可以继续进行正常操作。但是,整个“保存异常(exception)以便以后重新抛出”的事情使我感到困惑。通常,建议不要存储用于重新抛出方法的异常。这很不寻常,似乎让我感到困惑。您的代码包含的惊喜越少,维护起来就越容易(三个月后包括您自己)。
关于c# - 在C#中,finally块前面有一个包罗万象的catch块有什么用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2041654/