我见过有人说,使用不带参数的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
{
  int i = 1/0; 
}
catch
{
  reader.Close();
  throw;
}

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

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

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

其他回答

如果你读过c#,你就会明白finally块是为了优化应用程序和防止内存泄漏而设计的。

CLR并不能完全消除泄漏……如果程序无意中保留了对不需要的对象的引用,就会发生内存泄漏

例如,当您打开一个文件或数据库连接时,您的机器将分配内存来处理该事务,除非执行了dispose或close命令,否则该内存将不会被保留。但是如果在事务处理期间发生了错误,则继续执行的命令将被终止,除非它在try..最后. .块。

Catch与finally的不同之处在于,Catch的设计目的是为您提供处理/管理或解释错误的方法。把它想象成一个人告诉你“嘿,我抓住了一些坏人,你想让我对他们做什么?” 而最终的目的是确保你的资源被正确地配置。想想某人,不管有没有坏人,他都会确保你的财产仍然安全。

你应该让他们俩永远合作下去。

例如:

try
{
  StreamReader reader=new  StreamReader("myfile.txt");
  //do other stuff
}
catch(Exception ex){
 // Create log, or show notification
 generic.Createlog("Error", ex.message);
}
finally   // Will execute despite any exception
{
  reader.Close();
}

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

“Finally”是一个声明,“你必须总是做一些事情来确保程序状态正常”。因此,如果存在异常可能会抛出程序状态,那么拥有一个异常总是很好的形式。编译器还会竭尽全力确保Finally代码运行。

“Catch”是“我可以从这个异常中恢复”的声明。您应该只从真正可以纠正的异常中恢复—不带参数的catch表示“嘿,我可以从任何异常中恢复!”,这几乎总是不正确的。

如果有可能从每个异常中恢复,那么它就真的是语义上的吹毛求疵,关于你所声明的意图是什么。然而,事实并非如此,而且几乎可以肯定的是,在你上面的框架能够更好地处理某些异常。因此,使用finally,让您的清理代码免费运行,但仍然让更有知识的处理程序来处理问题。

Try{…}catch{}并不总是坏的。这不是一种常见的模式,但当我无论如何都需要关闭资源时,我倾向于使用它,比如在线程末尾关闭(可能)打开的套接字。

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

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

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

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

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