实施 C# IDisposable

Implementing C# IDisposable

我正在尝试找出在使用 IDisposable 时在 C# 中处理 属性 需要做的事情。我可以看到模板,但我不确定是否实际处理对象。

我正在使用此站点上给出的示例: https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose

我添加了 3 个属性:

privInt:私有值类型。我会处理它吗,因为它可以保存在堆上,所以可能需要 GC?如果我愿意那么如何,不能设置为 null 或调用 dispose?如果不是,那么我认为它必须留给 GC - 但释放资源不是 Dispose 的重点吗?

NonIDisClassInstance - 我是否设置为空?够了吗

任何人都可以在下面评论我的实现并就什么是 correct/wrong 提出建议。

IDisClass - 只需调用 dispose

class BaseClass : IDisposable
{
   // Flag: Has Dispose already been called?
   bool disposed = false;

   // Public implementation of Dispose pattern callable by consumers.
   public void Dispose()
   { 
      Dispose(true);
      GC.SuppressFinalize(this);           
   }

   //Private value type
   private int privInt;

   //Private class that does not implement IDisposable
   Private NonIDisClass NonIDisClassInstance;

   //Private class that does implement IDisposable
   Private IDisClass IDisClassInstance;

   // Protected implementation of Dispose pattern.
   protected virtual void Dispose(bool disposing)
   {
      if (disposed)
         return; 

      if (disposing) {
         // Free any other managed objects here.
         //
      }

      // Free any unmanaged objects here.     
      DisposeOfThis = ????;
      NonIDisClassInstance = null;
      IDisClassInstance.Dispose();
      disposed = true;
   }

   ~BaseClass()
   {
      Dispose(false);
   }
}
  • 如果您使用的是非托管内存,则只需要 GC.SuppressFinalize(this); 和一个析构函数。如果没有,您可以安全地忽略它。
  • 在您的 Dispose 实现调用 this.IDisClassInstance?.Dispose(); 中,这就是您所需要的。

你的代码可以浓缩成这样。

class BaseClass : System.IDisposable
{

    public virtual void Dispose()
    {
        // never throw an exception from Dispose so prevent an NRE by using ?.
        this.IDisClassInstance?.Dispose();
    }

    //Private class that does not implement IDisposable
    private object NonIDisClassInstance;

    //Private class that does implement IDisposable
    private IDisposable IDisClassInstance;
}

请记住,使用 Dispose 不一定要释放内存,而是要清理/释放 非托管资源,其中可能还包括内存。诸如打开文件流或数据库连接或网络连接之类的东西。

请注意,您的派生类型可以覆盖 Dispose,但这些覆盖的方法应包括对 base.Dispose(); 的调用,以便释放基础 class 的托管资源。