【问题标题】: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。

【问题讨论】:

    标签: c# idisposable resource-management


    【解决方案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
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-10
        相关资源
        最近更新 更多