【发布时间】:2012-04-15 17:27:28
【问题描述】:
在类 B 的最后一个实例最终确定之前,如何将类 A 的实例定义为存在,我不是 100% 清楚。
或者换句话说,我希望所有 B 在 B 最终确定内的 A 中调用 close&dispose 方法...这发生在 A 本身完成之前。
场景:
A.我有一个非托管资源的托管包装器。打个比方,我们把 A 称为文件系统
B.引用 A 的托管资源,这些资源又通过 A 包装器请求非托管资源。为了类比,我们称 B 为文件。
附加请求 --> 我希望 using 语法能够很好地发挥作用。即显式调用 using dispose 不应释放非托管资源。该对象将存在于对象池中。它应该只在它离开对象池时被释放。
class SomeClass() : IDisposable{
public SomeClass(){}
public ~SomeClass(){
// dispose of unmanaged here?
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
public void Dispose(bool disposing) {
if (disposing) {
// dispose managed
} else {
// dispose unmanaged?
}
}
public void Dispose() {
Dispose(true);
//GC.SuppressFinalize(this);
}
}
参考资料:
[1]Why Finalize method not allowed to override
[2] CLR 通过 C Sharp 第三版。通道。 21. 关键终结器对象。特别是第 537 页“使用托管资源完成”
【问题讨论】:
-
您正在尝试完成垃圾收集器所做的工作。只要存在对 B 对象的实时引用,就无法收集 A。一旦收集了所有 B,A 也将被收集。现在,它们最终确定的顺序不再重要了。
-
@HansPassant:这是否包括 IsFinalizingForUnload + HasShutdownStarted 场景?
-
这些条件没有什么特别之处,只是程序关闭时的终结器扫描。我很不清楚你为什么要为此烦恼。
-
@HansPassant:这一切都是在发现 Dispose (通过使用)关闭了不应该关闭的代码之后开始的。这导致试图更好地处理 dispose + unmanaged ......并且......结果发现了一些边缘案例 + .net 框架约定。
-
@HansPassant:学习易碎+复活会给人信心。顺便说一句:在这种情况下,不最终实现子对象(如框架所做的那样)是最好的前进方式。顺便说一句:AddMemoryPressure、RemoveMemoryPressure 和 ReRegisterForFinalize 看起来对于某些罕见的情况非常有用。否则我不会知道他们。