如何处理一次性对象抛出的异常?

时间:2012-08-01 09:17:59

标签: c# idisposable

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

  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();
        }
    }
    
  3. 更新

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

8 个答案:

答案 0 :(得分:10)

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

这很好

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

答案 1 :(得分:3)

这样做:

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

当一次性对象超出using子句的范围时,它们总是被处理掉,即使它是异常的。

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

答案 2 :(得分:3)

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

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();
  }

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

如果可能,您应该使用使用块。它将保证在您的对象上调用Dispose。手动执行此操作容易出错。

答案 6 :(得分:0)

using (IDisposable disp = new IDisposable())
{
   //some logic here
}

此代码将翻译成以下内容:

IDisposable disp = new IDisposable();

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

块“finally”中的代码始终执行,因此它为您提供了抛出异常的可能性,使用块返回,而不会怀疑Dispose不会被调用。

但是你应该小心使用和对象初始化器。

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

here属性可以看出,Position可以抛出异常。问题是该对象将被创建并且这将在 out of try block 中完成,因此可能存在内存泄漏。正确的方法

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

答案 7 :(得分: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,因为范围问题,也因为它更容易阅读。