4

.netに次のように書くことは合法ですか?

   public class A
    {
        public int i = 0;
        ~A()
        {
            Aref = this;
        }
    }


    public static A Aref;
    static void Main(string[] args)
    {
        Aref = new A();
        int gen = GC.GetGeneration(Aref);
        Aref = null;
        GC.Collect(gen, GCCollectionMode.Forced);
        GC.WaitForPendingFinalizers();
        Console.WriteLine(Aref.i);
        Console.ReadLine();
    }

期待どおりに動作し、コンソールに「0」を書き込みますが、常に動作することが保証されているのではないかと思います。

誰かが舞台裏で何が起こっているのか知っていますか?

4

3 に答える 3

8

それは復活と呼ばれ、合法です。「.net オブジェクトの復活」(およびそれに類する用語) を Google で検索すると、次のようなものが見つかります。

復活と .NET ガベージ コレクター

オブジェクト復活

これらのゾンビオブジェクトが戻ってこないようにして、脳か何かを食べてみてください. すべてのネクロマンシーと同様に、これは危険なものです。(主に、クラス階層の上位にあるファイナライザーがいくつかの重要なリソースを解放した可能性があるためです。また、オブジェクトが「参照されていない」場合、 を呼び出さない限り、ファイナライザーは再度実行されないことに注意してくださいGC.ReRegisterForFinalize。)

于 2009-03-03T14:44:23.630 に答える
1

最初のガベージ コレクションではインスタンスが収集されないため、機能します。ファイナライザーを実行するようにインスタンスをスケジュールするだけです。その後、ファイナライザーはインスタンスへの新しいルートを作成するため、次のコレクションが発生したときに、インスタンスは実際にはルート化されているため、コレクションの対象にはなりません。

このタフさには細心の注意を払う必要があります。オブジェクトが確実に破棄されるようにするためにファイナライザーが使用されている場合、これは実際にはプロトコルに違反しています。

于 2009-03-03T14:50:09.000 に答える
0

ガベージ コレクターは、オブジェクトを次の 3 つのグループに分けます。

  1. 最後にルート化された参照がファイナライズキューの外に存在することを確認したため、まだ生きているもの。
  2. ルート化された参照がどこにも存在しないため、削除する必要があるもの。
  3. ルート化された参照がファイナライズ キューに存在するため、ファイナライズする必要があるもの。
ルート化された参照がどこにもない場合を除き、オブジェクトを削除することはできません。ファイナライズは、削除前の明確な段階です。オブジェクトがファイナライズのために登録されている間、それが直接的または間接的に参照するすべてのオブジェクトは削除から保護されますが、ファイナライズからは保護されないことに注意してください。

于 2010-12-02T08:06:13.033 に答える