7

假设 Constructor 和 Process 方法可能抛出异常,使用 Disposable 对象的最佳方法是什么?我通常更喜欢以下实现之一。

  1. 使用块尝试捕获周围

    try
    {
        using (Disposable dispObj = new Disposable())
        {
            dispObj.Process();
        }
    }
    catch (Exception ex)
    {
        // Do something
    }
    
  2. try-catch-finally 块。

    Disposable dispObj2 = null;
    try
    {
        dispObj2 = new Disposable();
        dispObj2.Process();
    }
    catch (Exception ex)
    {
        // Do something
    }
    finally
    {
        if (dispObj2 != null)
        {
            dispObj2.Dispose();
        }
    }
    

更新:

再次:“假设 Constructor 和 Process 方法可能会抛出异常”。我真的不明白为什么没有人关心他们的答案中的异常。

4

8 回答 8

10

using很好。它有一个内置的 try-finally 块。如果发生异常,会自动调用 dispose 方法。

这可以

using (Disposable dispObj = new Disposable())
{
    dispObj.Process();
}
于 2012-08-01T09:19:20.673 回答
3

using 语句在后台使用 try - finally,并且仅适用于实现 IDisposable 的对象。您不必将 try catch 与 using 一起使用。请看以下示例(来自MSDN - using 语句)。

using (Font font1 = new Font("Arial", 10.0f)) 
{
    byte charset = font1.GdiCharSet;
}

上面的代码是一样的:

Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
于 2012-08-01T09:23:52.463 回答
3

像这样做:

using (Disposable dispObj = new Disposable())
{
    dispObj.Process();
}

一次性对象总是在它们超出using子句范围时被处置,即使它是由异常引起的。

并且不要使用空的catch {},完全没有意义的。

于 2012-08-01T09:20:30.613 回答
2
using (Disposable dispObj = new Disposable())
    {
        dispObj.Process();
    }
}
于 2012-08-01T09:20:18.730 回答
1

实现 IDisposable 接口的类通常使用 .NET 框架垃圾收集器无法清理的资源。调用 IDisposable.Dispose() 方法会执行将宝贵资源显式释放回世界的代码。实现 IDisposable 接口的类的一个主要示例是 SqlConnection 类。SqlConnection 类使用 Microsoft SQL Server 数据库连接。由于 SQL Server 支持的连接数量有限,因此尽快释放连接非常重要。通常,您不会直接调用 Dispose() 方法。通常,您会利用代码中的 Using 语句,就像您在代码中提到的那样

于 2012-08-01T09:21:48.833 回答
0

您提出的方法#1 可能是实现您想要的最简洁的方法。

周围的try...catch块应该捕获任何抛出的异常,包括构造函数抛出的异常。如果在一次性对象正在使用(using块内)时发生异常,则该对象也将在catch接管之前被处置。

方法#2 采用与方法#1 不同的执行路径。请注意,根据C# Reference,方法 #1 从字面上编译,就好像以下内容一样:

try
{
    {
        Disposable dispObj = new Disposable();
        try
        {
            dispObj.Process();
        }
        finally
        {
            if (dispObj != null)
                ((IDisposable)dispObj).Dispose();
        }
    }
}
catch (Exception ex)
{
    // Do something
}

所以,这两种方法的作用域是不同的。如果可能,我会更喜欢方法#1,因为范围问题,也因为它更容易阅读。

于 2014-12-26T17:52:57.987 回答
0

在可能的情况下,您应该使用 using 块。它将保证在您的对象上调用 Dispose。手动操作很容易出错。

于 2012-08-01T09:20:40.380 回答
0
using (IDisposable disp = new IDisposable())
{
   //some logic here
}

这段代码将被翻译成这样:

IDisposable disp = new IDisposable();

try
{
  //some logic here
}
finally
{
  if (disp != null)
     ((IDisposable)disp).Dispose();
}

块中的代码“最终”始终执行,因此它使您有可能抛出异常,从使用块中返回,毫无疑问 Dispose 不会被调用。

但是你应该小心使用和对象初始值设定项。

using (var fs = new FileStream(@"C:\blabla", FileMode.Open) { Position = pos })
{
    //some logic here
}

这里可以看出,属性 Position 可以抛出异常。问题是对象将被创建,这将在try 块之外完成,因此可能存在内存泄漏。正确的方法

using (var fs = new FileStream(@"C:\blabla", FileMode.Open))
{
    fs.Position = pos;
    //some logic here
}
于 2012-08-01T09:41:06.853 回答