尝试{.}之间的区别抓住{..}最后和没有它



这样的代码有什么区别:

string path = @"c:userspublictest.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
    file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
    Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
finally
{
    if (file != null)
    {
        file.Close();
    }
}

而这个:

string path = @"c:userspublictest.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
    file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
    Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
if (file != null)
{
    file.Close();
}

在这个结构中真的是最终需要的块。为什么Microsoft提供这样的结构?这似乎是多余的。不是吗?

想象一下,如果发生了一些你没有处理过的其他异常,例如ArgumentOutOfRangeException,或者如果你想重新抛出异常或从你的catch块中抛出一个包装的异常:

  1. 第一个块将确保关闭文件,无论是否发生异常。

  2. 第二个块仅在未发生异常或发生IOException时关闭文件。它不处理任何其他情况。

:注:第一个块还确保在从 catch 块本身内部抛出异常时关闭文件。

即使存在未捕获的异常,第一个块也会关闭文件。

仅当没有异常或捕获任何引发的异常时,第二个块才会关闭文件。

第一个也将确保如果try具有breakgotoreturncontinue或任何其他会导致执行移动到try块之外的跳转结构,则文件被关闭。 第二个不会,因此可能会导致资源未关闭。

在您的示例中,如果代码引发 System.IO.IOException 以外的异常,则不保证清理代码会运行。使用 finally 块,无论引发哪种类型的异常,其中的代码都将运行。

想象一下catch{}内部有一个异常,里面的代码最终仍然可以运行,但if (file != null){}块不会。

在这种情况下,

它是多余的。

例如,如果您将重新抛出异常并且仍然希望在块之后运行一些代码,则非常有用:

try {
  // do something dangerous
} catch(...) {
  // log the error or something
  throw; // let the exception bubble up to the caller
} finally {
  // this always runs
}
// this only runs if there was no exception

另一个示例是,如果 catch 可能出于其他原因引发异常:

try {
  // do something dangerous
} catch(...) {
  // handle the error
  // log the error, which may cause a different exception
} finally {
  // this runs even if the catch crashed
}
// this only runs if there was no exception, or the code in the catch worked

简单地说,由于代码可能会由于您可能甚至不知道的很多原因而崩溃,因此将清理放在finally块中以确保它无论发生什么都会运行是很有用的。

相关内容

  • 没有找到相关文章

最新更新