我该如何inheritanceIDisposable?
class级名称已被更改以保护无辜者 。
如果我有一个名为ISomeInterface的接口。 我还有inheritance接口的类,FirstClass和SecondClass。 FirstClass使用必须处理的资源。 SecondClass没有。
所以问题是,我应该从IDisposableinheritance哪里? 以下两个选项似乎都不太理想:
1) 使FirstClassinheritanceIDisposable 。 然后,任何处理ISomeInterfaces的代码都必须知道是否要处理它们。 这闻起来像是与我紧密耦合。
2) 使ISomeInterfaceinheritanceIDisposable 。 然后,任何从它inheritance的类都必须实现IDisposable,即使没有任何东西可以处理。 除了注释之外,Dispose方法基本上是空白的。
#2对我来说似乎是正确的选择,但我想知道是否有其他选择。
如果抽象实体(接口或抽象类)有可能需要是一次性的,它应该实现它。 例如, Stream
本身不需要IDisposable
, IEnumerator
也不…
抽象基类可能更简单,因为您可以使用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
代码通常没有特别的理由相信返回的枚举器实际上需要清理,也不相信它不会。 让IEnumerator
所有实现实现IDisposable
通常更快,让所有消费者在返回的枚举器上调用Dispose
,而不是让消费者检查返回的类型是否实现IDisposable
并调用它(如果是这样)。
如果预期基类型引用通常仅由不负责清理有问题项的方法使用,则基本类型不需要实现IDisposable
。 负责清理的代码将知道它正在处理的对象实现IDisposable
是否基类型。