如何使用 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 对它们一无所知,所以它不能收集和释放它们,除非你有意释放它们。如果不这样做,将会出现内存和句柄泄漏,最终会导致应用程序崩溃。
我不知道如何处理包含具有 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 对它们一无所知,所以它不能收集和释放它们,除非你有意释放它们。如果不这样做,将会出现内存和句柄泄漏,最终会导致应用程序崩溃。