如何处理封装了一次性实例的类?
Posted
技术标签:
【中文标题】如何处理封装了一次性实例的类?【英文标题】:How to deal with a class than encapsulates a disposible instance? 【发布时间】:2011-06-01 17:27:59 【问题描述】:interface IMyInterace
void Open();
object Read();
void Close();
class MyImplementation : IMyInterface
public void Open() /* instantiates disposible class */
//...
public void Close() /* calls .Dispose(); */
是否有处理这种情况的好方法,以确保调用类中的可处置实例? (除了在文档中,没有信号通知调用者他们必须调用“关闭”。)IMyInterface 的实现不一定封装 IDisposible 实例,并且在应用程序的整个生命周期中反复关闭和重新打开。
我正在考虑这样做:
在 MyImplementation 中实现 IDisposible。 将 Dispose() 设置为调用 Close()。 添加对 Close() 或 Dispose() 的调用到 开始开放,以确保以前 通话已结束。IMyInterface 的用户不知道他们使用的是什么实现,所以我不确定使 MyImplementation disposible 有多少价值,而且并非所有实现都会封装 IDisposibles。
【问题讨论】:
【参考方案1】:处理这个问题的标准方法是让MyImplementation
实现IDisposable
。
【讨论】:
【参考方案2】:正如约翰所说,你的第一个要点是正确的。
有时Close()
方法在功能上与Dispose()
同义,存在是为了保持与抽象的语义一致性。也就是说,补充Open()
方法。其他时候,Close()
将允许您重新打开,但 Dispose()
不应该。因此,您的第二个要点也很好。
要点 3 不一定适用,因为不应重复使用已处置的对象。如果你需要再次调用Open()
,你需要使用一个新的实例。实际上,一旦调用了Dispose()
(通过检查私有disposed
布尔标志),Open()
方法应该抛出一个ObjectDisposedException
。如果您希望对象在关闭后支持重新打开,您可以考虑使用Debug.Assert()
和/或如果在没有Close()
的情况下调用Open()
,则抛出异常。这将有助于防止对这些实例的草率管理。
一定要遵循完全一次性的模式,这比简单地实现接口更复杂:
bool disposed;
public void Dispose() // don't make virtual!
Dispose(true);
GC.SuppressFinalize(this);
protected virtual void Dispose(bool disposing)
if(!disposed)
if(disposing)
// dispose of managed resources here, for example:
// if(resource != null) resource.Dispose();
// dispose of unmanaged resources here
disposed = true;
【讨论】:
您不需要完整的 Disposable 模式。不需要析构函数,因此不需要 SuppressFinalize。【参考方案3】:除了这里已经有的答案:
如果这个类(经常/有时)仅通过接口使用,我建议从 IDisposable 继承 IMyInterace。
这将使您的用户以一致的方式使用这些对象。缺点当然是您可能需要向实际上不需要它的类添加(虚拟)Dispose 方法。但好处在于一致性和灵活性:如果一个类在未来发生变化以至于它确实需要 Dispose() 怎么办?
最小的方法:
interface IMyInterace : IDisposable
sealed class MyImplementation : IMyInterface
public void Open() /* instantiates disposible class */
public void Close() /* calls _myField.Dispose(); */
public void Dispose() Close(); // only use this short form in a sealed class
【讨论】:
以上是关于如何处理封装了一次性实例的类?的主要内容,如果未能解决你的问题,请参考以下文章
如何处理我的 AWS EC2 实例上的多个 Python 请求?