我见过有人说,使用不带参数的catch是一种糟糕的形式,尤其是当catch什么都不做的时候:

StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
catch   // No args, so it will catch any exception
{}
reader.Close();

然而,这被认为是良好的形式:

StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
finally   // Will execute despite any exception
{
  reader.Close();
}

据我所知,将清理代码放在finally块和将清理代码放在try. catch块之后的唯一区别是,如果你在try块中有返回语句(在这种情况下,finally中的清理代码将运行,但try. catch块之后的代码将不会运行)。

否则,最后有什么特别的?


当前回答

try/catch块捕获所有异常的问题是,如果发生未知异常,您的程序现在处于不确定状态。这完全违背了快速失败规则——如果发生异常,您不希望程序继续运行。上面的try/catch甚至会捕获outofmemoryexception,但这绝对是程序不会在其中运行的状态。

Try/finally块允许您在快速失败的情况下执行清理代码。对于大多数情况,您只想在全局级别捕获所有异常,以便您可以记录它们,然后退出。

其他回答

使用finally,您可以清理资源,即使您的catch语句将异常抛出给调用程序。与包含空catch语句的示例相比,差别不大。但是,如果在catch中执行了一些处理并抛出错误,或者甚至根本没有catch, finally仍然会运行。

最大的区别是尝试…Catch将吞下异常,隐藏发生错误的事实。Try .finally将运行您的清理代码,然后异常将继续运行,由知道如何处理它的程序来处理。

try/catch块捕获所有异常的问题是,如果发生未知异常,您的程序现在处于不确定状态。这完全违背了快速失败规则——如果发生异常,您不希望程序继续运行。上面的try/catch甚至会捕获outofmemoryexception,但这绝对是程序不会在其中运行的状态。

Try/finally块允许您在快速失败的情况下执行清理代码。对于大多数情况,您只想在全局级别捕获所有异常,以便您可以记录它们,然后退出。

虽然下面两个代码块是等效的,但它们并不相等。

try
{
  int i = 1/0; 
}
catch
{
  reader.Close();
  throw;
}

try
{
  int i = 1/0;
}
finally
{
  reader.Close();
}

'finally'是意图揭示代码。您向编译器和其他程序员声明,无论如何都需要运行这段代码。 如果您有多个捕获块,并且有清理代码,那么您最终需要。如果没有最后,您将在每个catch块中重复清理代码。(干燥原理)

最后,积木是特殊的。CLR将finally块中的代码与catch块分开来识别和处理,并且CLR竭尽全力确保finally块始终执行。这不仅仅是编译器的语法糖。

Finally是可选的——如果没有资源可以清理,就没有理由使用“Finally”块。