在接口的实现可能或可能不需要处理的情况下,最好是要求所有实现必须由将界面标记为IDisposable
?
这会强制此接口的用户始终处置对象,即使某些实现可能没有必要。目标显然是确保实施始终无缝交换。另一种方法是让用户决定,这可能看起来更正确,但更难沟通。另一方面,考虑到仅具有用接口类型声明的符号的用户,要求无条件地处理它可能看起来更正确。在这个推理中是否存在权衡或谬误?
如果问题过于依赖于这种情况,我想在教科书库(存储库设计模式)的上下文中构建它,其中大多数已知的实现需要处理的。
答案 0 :(得分:2)
如果问题过于依赖于这种情况,我想在教科书库(存储库设计模式)的上下文中构建它,其中大多数已知的实现都需要处理。
如果您正在编写实例化对象并负责其生命周期的库代码,那么理想方案将是处理 IDisposable
,但不是需求它除非绝大多数可能大多数实现需要清理;例如,在代码完成未知对象时使用is
或as
。它很少像这样简单,但例如:
IFoo obj = (IFoo)Activator.CreateInstance(unknownType);
using(obj as IDisposable)
{
// TODO: code
}
答案 1 :(得分:2)
在决定IFoo
是否应该实施IDisposable
时,关键问题不应该是实施IFoo
的大部分类型是否需要处置,或者是否需要处理大部分需要处理实现IFoo
的对象实例,而是由返回类型为IFoo
的工厂方法返回的实例中的任何非平凡部分是否可能需要由该工厂方法的调用者处理。
考虑IEnumerator
。实现它的类中只有一小部分需要处理(通过引入迭代器,分数可能会显着增加),但绝大多数实例将通过调用工厂方法IEnumerable.GetEnumerator()
获得,其返回类型为IEnumerator
。调用IEnumerable.GetEnumerator()
的代码通常不知道返回的对象是否需要处理;对于语义正确性,除非代码知道它使用的IEnumerable
的类型不会返回需要处理的实例,否则为了正确性必须将返回的工具强制转换为IDisposable
,如果结果为非-null,处理它们。
当Microsoft实施IEnumerator<T>
时,他们意识到消费者不得不尝试将枚举器强制转换为IDisposable
的负担远远大于实施者必须实施无操作的负担{{} 1}}方法。语义正确性要求消费者在任何实现Dispose
的枚举器上调用Dispose
,并且在已知实现它的类型上无条件地调用do-nothing IDisposable
方法比测试更容易,更快速是否可以实现Dispose
的类型。
即使只有1%的IDisposable
实现实现IEnumerator<T>
,绝大多数消费者也必须假设语义正确 / em>的。 IDisposable
继承IEnumerable<T>
并没有赋予消费者任何他们原本无法承担的义务 - 只是让他们更容易履行他们在任何情况下都会拥有的义务< / em>的
答案 2 :(得分:1)
所以,你正在公开一个界面
ISomeInterface
如果您打算使用此界面来触发处理,即您想要致电Dispose
,那么它应该实施IDisposable
。
ISomeInterface : IDisposable
但是,请考虑无处不在的IDisposable
的组合肯定会导致ISomeInterface
实施的第三方用户明确地或在Dispose
块中调用using
这些内容
如果您不打算自己致电Dispose
,请将选择留给具体的班级实施者。只有他们才能决定在特定情况下是否需要处置。
现在我可以quote an authoritative source,
不要求它,除非绝大多数实现都需要清理
我建议在Stream
的例子中,“绝对有可能”。
答案 3 :(得分:0)
最近再次思考这个问题,我想分享另一个指南/经验法则,如果适用,可能会使决策更容易。
没有人考虑的是用户/实施的比例:
如果有多个用户而不是实现,特别是如果这些实现都在您的控制之下,则考虑标记接口IDisposable
并强制用户始终处置如果不是绝对必要的话。只要这种情况适合手头的用例,它最有可能使用户的生活更简单:他们不需要检查他们是否需要处置,他们'我会系统地做。缺点是您必须为那些不需要它的实现实现虚拟Dispose
方法。除非你有特殊的性能要求,否则这个调用完全没问题(我认为唯一的开销是虚拟表查找,方法本身可能已经优化了)。
如果有比用户更多的实现,例如在插件系统的情况下,则考虑验证对象是否在您的核心中动态实现IDisposable
,以便实现不必实现伪IDisposable
方法。缺点是你的核心需要额外的逻辑。开销是演员和演员的开销。空检查。
tl; dr:我们经常假设用户数量多于实施数量。情况并非总是如此。
当然,这只是问题的一个维度,您可以使用它来决定;另一个维度是需要处理的实现与不需要处理的实现之间的比率。有关此方面的讨论,请参阅其他答案。
一旦你对每一个进行了评估,请立即考虑所有因素,与您的意见保持一致,并做出决定。