3

オブジェクトが GC.SuppressFinalize を呼び出したかどうかを検出する方法はありますか?

次のようなオブジェクトがあります (明確にするために完全な Dispose パターンは省略されています)。

public class ResourceWrapper {
    private readonly bool _ownsResource;
    private readonly UnmanagedResource _resource;

    public ResourceWrapper(UnmanagedResource resource, bool ownsResource) {
        _resource = resource;
        _ownsResource = ownsResource;
        if (!ownsResource)
            GC.SuppressFinalize(this);
    }
    ~ResourceWrapper() {
        if (_ownsResource)
            // clean up the unmanaged resource
    }
}

ownsResourceコンストラクターのパラメーターがの場合false、ファイナライザーは何もする必要がありません。そのためGC.SuppressFinalize、コンストラクターから直接呼び出すのが妥当なようです (少し変わっている場合)。ただし、この動作は風変わりなので、XML doc コメントに書き留めておきたいと思います...コメントしたい場合は、単体テストを作成する必要があります。

しかし、System.GCにはオブジェクトのファイナライズ可能性を設定するメソッド( SuppressFinalizeReRegisterForFinalize ) がありますが、オブジェクトのファイナライズ可能性を取得するメソッドはありません。Typemock を購入するか、独自の CLR ホストを作成する以外に、特定のインスタンスで GC.SuppressFinalize が呼び出されたかどうかを照会する方法はありますか?

4

3 に答える 3

4

これは不可能です。GCはこの情報を提供しません。その理由は、オブジェクトが存在できるのは2つの状態だけではありません。また、すでにファイナライズキューにあるか、すでにファイナライズされている可能性があります。

カスタムCLRホストはそれを支援しません。ホスティングインターフェイスはgcへのフックを提供しません。ファイナライザーでこれをチェックするだけで、必要なときにSuppressFinalizeが呼び出されたかどうかを確認できます。(すばやく)ログに記録します。反対を証明することはできません。

Fwiw、.NETフレームクラスはこれを行いません。とにかくファイナライザーを実行させるだけです。

于 2011-01-08T16:16:49.343 に答える
3

オブジェクトがリソースを所有していない場合にファイナライズが抑制されていることを確認したい場合は、ファイナライザーにリソースを所有していると主張させることができますか? テストでは GC.Collect と GC.WaitForPendingFinalizers を実行する必要がありますが、製品コードには assert (製品ビルドから省略できる) 以外の余分なものはありません。アサートに関する 1 つの注意事項: オブジェクトを作成してから所有権ステータスを設定するまでの間に、オブジェクトを作成するスレッドが停止した場合、ファイナライザーが不適切に実行される可能性があります。

そうは言っても、問題のリソースを所有する、または所有しない個別のサブタイプ OwnedResourceWrapper と SharedResourceWrapper を持つ抽象的な ResourceWrapper 型を使用する方が良いかどうかは疑問です。その場合、リソースを所有しないサブタイプは、そもそもファイナライザーを持つ必要がありません。SharedResourceWrapper が IDisposable を no-op として実装すると便利な場合があることに注意してください。

于 2011-01-13T15:39:26.770 に答える
2

これは役立つかもしれません(帰謬法)。トリックは、ファイナライザーでログ(これは静的な状態である可能性があります)を実行することです。誰かが不在の場合、彼は抑制ファイナライズを呼び出しましたが、それでもいつかはわかりません。

あなたがそのタイプの作者である場合、これは機能しています。

于 2011-01-08T16:22:14.930 に答える