【问题标题】:Instance method call Dispose实例方法调用 Dispose
【发布时间】:2014-10-12 14:28:33
【问题描述】:

公共方法在同一个类中调用IDisposable的Dispose是否正确?

例如

public class Worker : IDisposable
{
    public void Close()
    {
       SendCloseCommand();
       Dispose();
    }

    public void Dispose()
    {
       ////other resources release
    }

    private void SendCloseCommand()
    {
    }
}

关于一次性图案的另一件事: 如果始终调用 Close,那么从 Dispose 方法调用更好还是不调用?

如果没有,我应该把 Worker 类的用法放在一个 try/catch/finally 中,以调用 Close。对吧?

正确的设计应该是?

public class Worker : IDisposable
{
    public void Close()
    {
       SendCloseCommand();
    }

    public void Dispose()
    {
       Close();
       ////other resources release
    }

    private void SendCloseCommand()
    {
        ////other stuff
    }
}

【问题讨论】:

    标签: c# design-patterns dispose idisposable


    【解决方案1】:

    Microsoft 有一些关于在实现IDisposable 的类上使用Close 方法的建议。它是Dispose Pattern 指南的一部分:

    考虑提供方法Close(),除了Dispose(),如果关闭是该领域的标准术语。

    这样做时,务必使 Close 实现与 Dispose 相同,并考虑显式实现 IDisposable.Dispose 方法。

    public class Stream : IDisposable {
        IDisposable.Dispose(){
            Close();
        }
        public void Close(){
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
    

    所以微软的建议是隐藏Dispose 并让它调用Close 来进行实际的清理。另外,请记住多次调用Dispose 的准则:

    允许多次调用Dispose(bool) 方法。该方法可能会在第一次调用后选择不执行任何操作。

    遵循这些准则可以使您的代码与 .NET 库保持一致,并且您将避免混淆是否应该关闭或处置您的类以进行适当的清理。

    【讨论】:

      【解决方案2】:

      如果你查看Microsoft implementation for StreamReaderDispose 会从Close 调用,

      public override void Close()
      {
          Dispose(true);
      }
      

      还有Dispose 的实现也通过调用基础StreamClose 来关闭流。

      protected override void Dispose(bool disposing)
      {
          // Dispose of our resources if this StreamReader is closable.
          // Note that Console.In should be left open.
          try {
              // Note that Stream.Close() can potentially throw here. So we need to 
              // ensure cleaning up internal resources, inside the finally block.  
              if (!LeaveOpen && disposing && (stream != null))
                  stream.Close();
          }
          finally {
              if (!LeaveOpen && (stream != null)) {
                  stream = null;
                  encoding = null;
                  decoder = null;
                  byteBuffer = null;
                  charBuffer = null;
                  charPos = 0;
                  charLen = 0;
                  base.Dispose(disposing);
              }
          }
      }
      

      在您的类实现中,我会从您的Close 方法调用Dispose,就像您在第一个代码sn-p 中所做的那样。在Dispose 中,我会检查Worker 的状态,如果它没有关闭则使用SendCloseCommand 关闭它,然后释放资源。

      public void Dispose()
      {
         if(this.Status != Closed) // check if it is not already closed
           {
               SendCloseCommand();
           }
      
         ////other resources release
      }
      

      这将确保您的资源处置,即使您的课程与using 语句一起使用,或者如果任何人手动调用Close

      请记住在发出关闭命令之前检查您的Worker 对象的状态。

      【讨论】:

      • 事实上,我同意你的例子,我不想用 try/catch/finally 填充代码,而是简单地使用 using 语句。
      猜你喜欢
      • 1970-01-01
      • 2016-08-30
      • 2020-09-19
      • 1970-01-01
      • 2017-10-27
      • 2019-10-28
      • 1970-01-01
      • 2016-07-29
      • 1970-01-01
      相关资源
      最近更新 更多