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

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

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

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

应该Dispose()方法的实现是幂等的

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

从在MSDN上实现Dispose方法 :

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

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

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

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

来自MSDN:

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

个人 – 是的 – 我总是让Dispose()幂等。

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

但是,同样地,在某些应用中,它可能不那么清楚。

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

鉴于使Dispose幂等相对容易(即如果已经处理掉,什么都不做),那么它似乎很愚蠢。