1

在B类的最后一个实例最终确定之前,我并不是 100% 清楚如何将A类的实例定义为存在。

或者换句话说,我希望所有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]为什么 Finalize 方法不允许覆盖

[2] CLR 通过 C Sharp 第三版。通道。21. 关键终结器对象。特别是第 537 页“使用托管资源完成”

4

1 回答 1

2

您通常无法控制最终确定顺序。不过,您可以使用CriticalFinalizerObject控制两阶段顺序。还要查看 SafeHandle 基础架构以及 FileStream 是如何做到的。

如果这还不够,您可以通过从静态类成员(例如列表或字典)创建对象引用来任意控制生命周期。只有当您释放这些引用时,才会发生最终确定。因此,您将创建一个对 A 的引用,一旦您注意到对 B 的 GCHandle 已变得无效,您就会清除该引用。

于 2012-04-15T17:32:17.483 回答