如何处理封装一次性实例的类?

5
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实例,并且在应用程序的生命周期内会反复关闭和重新打开。
我考虑这么做:
- 在MyImplementation中实现IDisposible。 - 将Dispose()设置为调用Close()。 - 在Open的开始处添加对Close()或Dispose()的调用,以确保之前的调用已关闭。
使用IMyInterface的用户不知道他们正在使用哪个实现,因此我不确定使MyImplementation可丢弃有多少价值,而且并非所有实现都将封装IDisposibles。
3个回答

5
处理这个问题的标准方法是让 MyImplementation 实现 IDisposable 接口。

3

正如John所提到的,你所列举的第一个要点是正确的。

有时候,Close() 方法在功能上跟 Dispose() 是同义词,用于保持语义上的一致性,即与一个抽象方法相对应。也就是说,为了补充一个 Open() 方法。其他情况下,Close() 允许你重新打开对象,但是 Dispose() 不应该这样做。因此,你的第二个要点也是正确的。

第三个要点并不一定适用,因为已经被处理的对象不应该被重复使用。如果需要再次调用 Open() 方法,则需要使用一个新实例。事实上,Open() 方法应该在调用 Dispose() 后抛出一个 ObjectDisposedException 异常(通过检查一个私有的布尔标志 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
你不需要完整的“可处置模式”。不需要析构函数,因此也不需要SuppressFinalize。 - H H

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

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接