IDisposable.Dispose()实现应该是幂等的吗?

时间:2012-01-19 09:42:43

标签: c# .net memory-management idempotent

Microsoft.NET框架提供IDisposable接口,该接口需要实现void Dispose()方法。其目的是实现IDisposable实现可能已分配的昂贵资源的手动或基于范围的发布。示例包括数据库集合,流和句柄。

我的问题是,如果Dispose()方法的实现是幂等的 - 当在同一个实例上多次调用时,该实例仅被“处置”一次,并且后续调用不会抛出异常。在Java中,大多数具有相似行为的对象(作为示例再次出现流和数据库连接)对于close()操作是幂等的,这恰好是Dispose()方法的模拟。

但是,我个人使用.NET(特别是Windows Forms)的经验表明,并非所有实现( .NET框架本身的一部分)都是幂等的,因此后续调用这些抛出ObjectDisposedException。这真的让我对如何处理一次性对象的实现感到困惑。该场景是否有共同的答案,还是取决于对象的具体上下文及其用法?

4 个答案:

答案 0 :(得分:19)

  

如果Dispose()方法的实现是幂等的

是的,它应该。没有人知道它会被召唤多少次。

来自MSDN上的Implementing a Dispose Method

  

Dispose方法应该可以多次调用而不会抛出异常。

具有良好实现IDispose的对象将具有一个布尔字段标志,指示它是否已经被处理掉,并且在后续调用中什么都不做(因为它已经被处理掉了)。

答案 1 :(得分:7)

是的,当对象已被处理时,还要确保在调用类时其他方法正确响应。

public void SomeMethod()
{
     if(_disposed)
     {
         throw new ObjectDisposedException();
     }
     else
     {
         // ...
     }

}

答案 2 :(得分:5)

From MSDN:

  

允许多次调用Dispose方法而不抛出异常。第一次调用后,该方法应该不执行任何操作。

答案 3 :(得分:3)

个人 - 是的 - 我总是使Dispose()具有幂等性。

在给定应用程序中对象的通常生命周期中,可能没有必要 - 从创建到处置的生命周期可能是确定性的并且是众所周知的。

然而,同样,在某些应用中,它可能不那么清楚。

例如,在装饰器场景中:我可能有一个一次性对象A,由另一个一次性对象B装饰。我可能想要显式处理A,但是B上的Dispose也可以处理它包装的实例(想想:流) )。

鉴于使Dispose幂等相对容易(即如果已经处理掉,什么也不做),看起来很愚蠢。