如何使用 Dispose/Finalize 方法正确处理 Class 变量

How to Properly Handle Class Variables with Dispose/Finalize Methods

我不知道如何处理包含具有 Dispose/Finalize 方法的变量的 class。我希望这个 class 包含它自己的 Dispose/Finalize 方法,这些方法调用每个变量的 Dispose;但是,C# 文档和 Whosebug 上的所有其他 answers/examples 都引起了一些混乱。

主要的混淆来自于没有明确区分什么是 "managed" 或 "unmanaged" 对象。例如,解释如何实现 Dispose 的文档 here 仅使用仅声明 "Free any unmanaged objects here." 或 "Free any other managed objects here."

的占位符注释

具有 Dispose/Finalize 的 class 变量属于托管类别还是非托管类别? (此外,我是否应该关注 class 不包含任何类型 Dispose/Finalize 实现的变量?考虑到有两种类型的 "management",这是否意味着没有 "Dispose"仍然需要以某种方式处理?)

即,处理此 class 的正确方法是什么?

class BaseClass : IDisposable {

   MyDisposeableObject disposeMe; // object with Dispose/Finalize
   Dictionary<string,int> anotherObject; // just some arbitrary other object

   bool disposed = false;

   public BaseClass() {
      disposeMe = new MyDisposeableObject();
      anotherObject = new Dictionary<string,int>();
   }

   public void Dispose() { 
      Dispose(true);
      GC.SuppressFinalize(this);           
   }

   protected virtual void Dispose(bool disposing) {
      if (disposed)
         return; 

      if (disposing) {
         // Free any other managed objects here.
         // Should I use "disposeMe.Dispose()" here?
      }

      // Free any unmanaged objects here.
      // OR should I use "disposeMe.Dispose()" here?

      // Also should I be doing anything with "anotherObject"?

      disposed = true;
   }

   ~BaseClass() {
      Dispose(false);
   }
}

这对我来说也是一个困惑,但是当我阅读更多关于 .Net 中的内存管理和 GC 机制时,一切都变得清晰了。

只有在 "disposing=true" 时才应调用 disposeMe.Dispose()。因为它是托管的 class/resource。我假设它也正确地实现了这个处置和析构函数模式。

为什么不应该尝试在 if(disposing) 块之外使用任何托管对象?

因为 GC 可能不会也不会按照从所有者到拥有的图表来收集您的对象。因此,当 Destructor 调用 Dispose 方法时,disposeMe 对象可能已经被收集并且无法访问。所以你可以not/should不把它放在这个区域。

但是你可以释放非托管资源,比如你分配的非托管内存空间,你打开的句柄...因为 GC 对它们一无所知,所以它不能收集和释放它们,除非你有意释放它们。如果不这样做,将会出现内存和句柄泄漏,最终会导致应用程序崩溃。