我该如何inheritanceIDisposable?

class级名称已被更改以保护无辜者

如果我有一个名为ISomeInterface的接口。 我还有inheritance接口的类,FirstClass和SecondClass。 FirstClass使用必须处理的资源。 SecondClass没有。

所以问题是,我应该从IDisposableinheritance哪里? 以下两个选项似乎都不太理想:

1) 使FirstClassinheritanceIDisposable 。 然后,任何处理ISomeInterfaces的代码都必须知道是否要处理它们。 这闻起来像是与我紧密耦合。

2) 使ISomeInterfaceinheritanceIDisposable 。 然后,任何从它inheritance的类都必须实现IDisposable,即使没有任何东西可以处理。 除了注释之外,Dispose方法基本上是空白的。

#2对我来说似乎是正确的选择,但我想知道是否有其他选择。

如果抽象实体(接口或抽象类)有可能需要是一次性的,它应该实现它。 例如, Stream 本身不需要IDisposableIEnumerator也不…

抽象基类可能更简单,因为您可以使用Dispose()的默认(空)实现,也可以使用终结器/ Dispose(bool)模式,即

 void IDisposable.Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) {} ~BaseType() {Dispose(false);} 

如果你知道ISomeInterface的某些实现需要处理,那么接口应该inheritanceIDisposable,即使接口的具体实现没有任何可处理的东西。

例如,在BCL中,IDataReader实现了IDisposable,即使可以想象数据读取器实现没有需要处理的外部资源。

这取决于你的界面,但我倾向于#2。 如果你有两个ISomeInterface实现,只有一个需要处理,那么你需要重构。

通常,当您绑定到接口时,最好让该接口inheritanceIDisposable而不是基类; 如果你的接口没有inheritanceIDisposable ,你必须强制转换为IDisposable来处置该对象,这就冒了InvalidCast的风险……

如果您希望所有代码一般地处理ISomeInterfaces,那么是的,它们都应该是一次性的。

如果没有,那么创建FirstClass的代码应该处理它:

 using (FirstClass foo = new FirstClass()) { someObjectThatWantsISomeInterface.Act(foo); } 

否则,你总是可以使用类似这种扩展方法:

 public static void DisposeIfPossible(this object o) { IDisposable disp = o as IDisposable; if (disp != null) disp.Dispose(); } // ... someObject.DisposeIfPossible(); // extension method on object 

我还应该提一下,我更喜欢模板基类方法。 我在这篇关于正确建造一次性物品的博客中对此进行了论述。

我的建议是转到根,而不是直接转到具体的类。 第2点是根,你是由FirstClass的某种契约驱动的。 如果您知道类必须实现某个接口,那么您希望确保它们签署合同的接口inheritance了IDisposable

到目前为止所写的所有答案都错过了一个关键点:只有基类型或基本接口才能实现IDisposable如果可能需要基类实例的代码可能会获得需要处理的实例的所有权 ,而不会意识到它。 可能发生这种情况的最常见情况是使用工厂方法; 一个主要的例子是IEnumerable / IEnumerator 。 大多数枚举器不需要清理,但调用IEnumerable.GetEnumerator代码通常没有特别的理由相信返回的枚举器实际上需要清理,也不相信它不会。 让IEnumerator所有实现实现IDisposable通常更快,让所有消费者在返回的枚举器上调用Dispose ,而不是让消费者检查返回的类型是否实现IDisposable并调用它(如果是这样)。

如果预期基类型引用通常仅由不负责清理有问题项的方法使用,则基本类型不需要实现IDisposable 。 负责清理的代码将知道它正在处理的对象实现IDisposable是否基类型。