3

正如 Overriding the Finalize 方法Object.Finalize 文档中所解释的那样,我曾经很确定答案是否定的。

但是,在 Reflector 中随机浏览FileStream时,我发现它实际上可以从终结器中调用这样的方法:

private SafeFileHandle _handle;

~FileStream()
{
    if (this._handle != null)
    {
        this.Dispose(false);
    }
}

protected override void Dispose(bool disposing)
{
    try
    {
        ...
    }
    finally
    {
        if ((this._handle != null) && !this._handle.IsClosed)  // <=== HERE
        {
            this._handle.Dispose();   // <=== AND HERE
        }
        [...]
    }
}

我开始想知道由于其编写方式的确切原因,这是否总是有效,因此“不要接触终结器中的托管类”是否只是一个指南,只要有充分的理由和必要的知识就可以打破它对。

我挖得更深一点,发现当“规则”被打破时可能发生的最坏情况是正在访问的托管对象已经完成,或者可能在单独的线程上并行完成。因此,如果 SafeFileHandle 的终结器没有做任何会导致后续调用 Dispose 失败的事情,那么上面应该没问题......对吗?

问题:那么毕竟可能存在这样的情况,即可以从终结器可靠地调用另一个托管类上的方法?我一直认为这是错误的,但这段代码表明这是可能的,并且有足够好的理由这样做。

奖励:观察到,SafeFileHandle甚至不会知道它是从终结器调用的,因为这只是对Dispose(). 基类 ,SafeHandle实际上有两个私有方法,InternalDisposeInternalFinalize, 在这种情况下InternalDispose会被调用。这不是问题吗?为什么不?...

4

1 回答 1

2

是的,终结器可以调用其他方法。见鬼,你甚至可以做一些有趣的事情,比如为最终确定重新注册类型。但是在处理可终结的实例时,您必须明确检查 null,因为不能保证终结器以任何顺序运行。

在这种情况下,只需尽可能好地关闭事物即可。如果句柄还没有最终确定,那么酷,让我们处理它,否则,好吧,终结器已经尽力了。

于 2010-05-08T00:03:28.793 回答