3

Overriding the Finalize methodObject.Finalize documentationで説明されているように、私は答えが「いいえ」であると確信していました。

ただし、FileStreamReflector をランダムにブラウジングしているときに、ファイナライザーからそのようなメソッドを実際に呼び出すことができることがわかりました。

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、実際には と の 2 つのプライベート メソッドがInternalDisposeありInternalFinalize、この場合InternalDisposeは が呼び出されます。これは問題ではありませんか?なぜだめですか?...

4

1 に答える 1

2

はい、ファイナライザーは他のメソッドを呼び出すことができます。たとえば、ファイナライズのために型を再登録するなど、面白いこともできます。ただし、ファイナライザーは任意の順序で実行されることが保証されていないため、ファイナライズ可能なインスタンスを処理する場合は明示的に null をチェックする必要があります。

その場合、できるだけうまく閉じるだけです。ハンドルがまだファイナライズされていない場合は、それを破棄しましょう。それ以外の場合は、ファイナライザーが最善を尽くしました。

于 2010-05-08T00:03:28.793 に答える