我见过有人说,使用不带参数的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块成功,它就会执行,如果你的try块失败,它就会执行catch块,然后是finally块。

此外,最好尝试使用以下结构:

using (StreamReader reader=new  StreamReader("myfile.txt"))
{
}

由于using语句被自动包装在try / finally语句中,流将自动关闭。(如果想要真正捕获异常,则需要在using语句周围加上try / catch)。

摄自:这里

引发和捕获异常不应该作为方法成功执行的一部分常规发生。在开发类库时,必须让客户端代码有机会在执行可能引发异常的操作之前测试错误条件。例如,System.IO.FileStream提供了一个CanRead属性,可以在调用Read方法之前进行检查,以防止引发潜在的异常,如下所示的代码片段:

Dim str As Stream = GetStream() If (str.CanRead) Then '代码来读取流 如果

The decision of whether to check the state of an object prior to invoking a particular method that may raise an exception depends on the expected state of the object. If a FileStream object is created using a file path that should exist and a constructor that should return a file in read mode, checking the CanRead property is not necessary; the inability to read the FileStream would be a violation of the expected behavior of the method calls made, and an exception should be raised. In contrast, if a method is documented as returning a FileStream reference that may or may not be readable, checking the CanRead property before attempting to read data is advisable.

To illustrate the performance impact that using a "run until exception" coding technique can cause, the performance of a cast, which throws an InvalidCastException if the cast fails, is compared to the C# as operator, which returns nulls if a cast fails. The performance of the two techniques is identical for the case where the cast is valid (see Test 8.05), but for the case where the cast is invalid, and using a cast causes an exception, using a cast is 600 times slower than using the as operator (see Test 8.06). The high-performance impact of the exception-throwing technique includes the cost of allocating, throwing, and catching the exception and the cost of subsequent garbage collection of the exception object, which means the instantaneous impact of throwing an exception is not this high. As more exceptions are thrown, frequent garbage collection becomes an issue, so the overall impact of the frequent use of an exception- throwing coding technique will be similar to Test 8.05.

从可读性的角度来看,它更明确地告诉未来的代码读者“这里的东西很重要,无论发生什么都需要完成。”这很好。

此外,空catch语句对它们来说往往有某种“味道”。它们可能表明开发人员没有仔细考虑可能发生的各种异常以及如何处理它们。

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块始终执行。这不仅仅是编译器的语法糖。