如何使用释放/终结方法正确处理类变量



我不知道如何处理包含带有Dispose/Finalize方法的变量的类。我希望这个类包含它自己的 Dispose/Finalize 方法,这些方法为每个变量调用 Dispose;但是,C#文档和StackOverflow上的所有其他答案/示例都引起了一些混乱。

主要的混淆来自于缺乏对什么是"托管"或"非托管"对象的澄清。例如,此处说明如何实现 Dispose 的文档仅使用占位符注释,这些注释仅声明"在此处释放任何非托管对象"或"在此处释放任何其他托管对象"。

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

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

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((。因为它是托管类/资源。我假设它也正确地实现了这种释放和析构函数模式。

为什么您不应该尝试使用 if(释放(块之外的任何托管对象?

因为 GC 可能不会也不会通过跟踪从所有者到拥有者的图表来收集您的对象。因此,当析构函数调用 Dispose 方法时,DisposeMe 对象可能已被收集且无法访问。所以你不能/不应该在这个区域处理它。

但是,您可以释放非托管资源,例如您分配的非托管内存空间、您打开的句柄...由于GC对它们一无所知,因此除非您有意释放它们,否则它无法收集和释放它们。如果不这样做,就会有内存和句柄泄漏,最终会导致应用程序崩溃。

最新更新