interface IMyInterace
{
void Open();
object Read();
void Close();
}
class MyImplementation : IMyInterface
{
public void Open() { /* instantiates disposible class */ }
//...
public void Close() { /* calls .Dispose(); */ }
}
有没有一种很好的方法来处理这种情况,以确保调用类中的可处置实例? (除了在文档中,调用者没有信号称他们必须调用'Close'。)IMyInterface的实现不一定封装IDisposible实例,并且在整个应用程序的生命周期内重复关闭和重新打开。
我正在考虑这样做:
IMyInterface的用户不知道他们正在使用什么实现,因此我不确定MyImplementation可处置的价值有多少,而且并非所有实现都会封装IDisposible。
答案 0 :(得分:5)
处理此问题的标准方法是让MyImplementation
实施IDisposable
。
答案 1 :(得分:3)
正如约翰所说,你的第一个要点是正确的。
有时,Close()
方法在功能上与Dispose()
同义,并且存在以保持与抽象的语义一致性。也就是说,补充Open()
方法。其他时候,Close()
会允许您重新打开,但Dispose()
不应该。因此,你的第二个要点也很好。
子弹点3不一定适用,因为不应重复使用被处置物体。如果您需要再次呼叫Open()
,则需要使用新实例。事实上,Open()
方法应该在调用ObjectDisposedException
后抛出Dispose()
(通过检查私有disposed
布尔标志)。如果您希望对象在关闭后支持重新打开,则可以考虑使用Debug.Assert()
和/或在没有Open()
的情况下调用Close()
时抛出异常。这将有助于防止这些情况的草率管理。
请务必遵循完整的一次性模式,这比简单实现界面更为重要:
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;
}
答案 2 :(得分:1)
除了已经有的答案:
如果此类(通常/有时)仅通过接口使用,我建议从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
}