当class有IDisposable成员但没有非托管资源时,我应该实现IDisposable吗?

mar*_*mnl 18 .net c#

StackOverflow上的MSDN文档和许多答案都是为了解决正确实现的问题IDisposable,例如MSDN IDisposable,MSDN实现IDisposable,优秀的StackOverflow Q&A

但是,它们似乎都没有涵盖我所拥有的更常见的用例:当我的班级有一个IDisposable比一个方法更长的成员时该怎么办?例如

  class FantasticFileService
  {
    private FileSystemWatcher fileWatch; // FileSystemWatcher is IDisposable

    public FantasticFileService(string path)
    {
      fileWatch = new FileSystemWatcher(path);
      fileWatch.Changed += OnFileChanged;
    }

    private void OnFileChanged(object sender, FileSystemEventArgs e)
    {
      // blah blah
    }
  }
Run Code Online (Sandbox Code Playgroud)

最接近的MSDN解决这个问题只涉及IDisposable短时间实例的用例,所以调用Dispose例如using:

仅在直接使用非托管资源时才实现IDisposable.如果您的应用只使用实现IDisposable的对象,请不要提供IDisposable实现.相反,您应该在完成使用后调用对象的IDisposable.Dispose实现.

当然,这里不可能我们需要实例比方法调用更长时间存活!?

我怀疑这样做的正确方法是实现IDisposable(将责任传递给我的类的创建者来处置它)但是没有所有的终结器和protected virtual void Dispose(bool disposing)逻辑,因为我没有任何无人管理的资源,即:

  class FantasticFileService : IDisposable
  {
    private FileSystemWatcher fileWatch; // FileSystemWatcher is IDisposable

    public FantasticFileService(string watch)
    {
      fileWatch = new FileSystemWatcher(watch);
      fileWatch.Changed += OnFileChanged;
    }

    public void Dispose()
    {
      fileWatch.Dispose();
    }
  }
Run Code Online (Sandbox Code Playgroud)

但为什么这个用例没有在任何官方文档中明确涵盖?IDisposable如果你的班级没有非托管资源,它明确表示没有实现这一事实让我犹豫不决......那么一个可怜的程序员要做什么?

gna*_*lck 20

看起来您的案例确实涵盖了一些文档,即设计警告CA1001:拥有一次性字段的类型应该是一次性的.

该链接有一个示例,说明您的IDisposable实现应该是什么样子.它将如下所示.最终设计指南可在CA1063中找到:正确实施IDisposable.

  class FantasticFileService : IDisposable
  {
    private FileSystemWatcher fileWatch; // FileSystemWatcher is IDisposable

    public FantasticFileService(string watch)
    {
      fileWatch = new FileSystemWatcher(watch);
      fileWatch.Changed += OnFileChanged;
    }

    ~FantasticFileService()
    {
      Dispose(false);
    }

    protected virtual void Dispose(bool disposing)
    {
      if (disposing && fileWatch != null)
      {
        fileWatch.Dispose();
        fileWatch = null;
      }
    }

    public void Dispose()
    {
      Dispose(true);
      GC.SuppressFinalize(this);
    }
  }
Run Code Online (Sandbox Code Playgroud)