我曾经非常确定答案是“否”,如Overriding the Finalize method和Object.Finalize documentation中所述。
然而,在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
实际上有两个私有方法,InternalDispose
和InternalFinalize
,在这种情况下,InternalDispose
将被调用。这不是问题吗?为什么不呢?...
答案 0 :(得分:2)
是的,终结者可以调用其他方法。地狱,你甚至可以做一些有趣的事情,例如重新注册类型以进行最终化。但是在处理可终结实例时你必须显式检查null,因为终止函数不能保证以任何顺序运行。
在这种情况下,这只是尽可能好地关闭事情的问题。如果手柄还没有最终确定,请冷却,让我们处理它,否则,最终确定器会做到最好。