为什么我们必须关闭finally{}块下的对象

本文关键字:对象 finally 我们 为什么 | 更新日期: 2023-09-27 18:19:38

有人能解释为什么#1方法比#2更好吗?

1

try
{
}
catch
{
}
finally
{
reader.Close();  
dataStream.Close();
response.Close();
}

2

try
{
reader.Close();  
dataStream.Close();
response.Close();
}
catch
{
}

为什么我们必须关闭finally{}块下的对象

如果reader.Close()引发异常,两个选项将永远不会关闭dataStreamresponse

但是,在#2选项中,如果reader.Close()之前的代码引发异常,则不会关闭任何对象。在#1中,您至少可以保证始终调用reader.Close(),即使其他事情引发了异常。

不过,通常情况下,任何具有Close()方法的对象都应该通过IDisposable.Dispose()实现Close,在这种情况下,我总是更喜欢使用using而不是以下任一选项:

using(var reader = CreateReader())
{
  using(var dataStream = CreateDataStream(reader))
  {
    using(var response = CreateResponse(dataStream))
    {
       // Use objects
    }
  }
}

这将强制所有对象正确关闭,但更干净。

我更喜欢方法3

using(var reader = ...)
using(var dataStream = ...)
using(var response = ...)
{
    //...
}//all disposed (and implicitly closed) at the end of this scope

使用这个构造,编译器将转换为大致如下:

var reader = ...;
var dataStream = ...;
var response = ...;
try
{
    //...
    //even if an error happens here
}
finally
{
   //this code still runs before control leaves this method.
   reader.Close();  
   dataStream.Close();
   response.Close();
}

由于Try块是为处理可能的失败而设计的,因此处理成功和不成功的情况都很重要。Try块中的项目可能会被调用,也可能不会被调用——这取决于失败是否发生以及在哪里发生。

通过将闭包语句放置到finally块中,可以确保无论Try部分是否成功,都将始终调用这些语句。这样,即使确实发生了故障,也不会留下读取器、数据流和响应。

如果在关闭所有对象之前,try块中的任何位置都发生异常,则不会关闭这些对象。finally块允许您在try块中引发异常时执行清理。

正如其他人所提到的,using方法是我使用自己的代码的方式。编译器将using转换为try{} finally{}块。查看以下MSDN链接:http://msdn.microsoft.com/en-us/library/yh598w02.aspx

干杯。