.NETデストラクタで「this」へのルート化された参照を再作成することは合法ですか?
-
03-07-2019 - |
質問
.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」を書き込みますが、常に動作することが保証されているかどうかは疑問です。
誰かが舞台裏で何が起こっているか知っていますか?
解決
これは復活と呼ばれ、合法です。 「.netオブジェクトの復活」のためのGoogle (およびそのような用語)、次のようなものがあります:
これらのゾンビオブジェクトが戻ってこないことを確認し、脳などを食べようとします。すべてのネクロマンシーと同様に、これは危険なものです。 (ほとんどの場合、クラス階層の上位のファイナライザがいくつかの重要なリソースを解放した可能性があります。また、 GC.ReRegisterForFinalize
。)
他のヒント
最初のガベージコレクションがインスタンスを収集しないため、機能します。ファイナライザを実行するようにインスタンスをスケジュールするだけです。その後、ファイナライザはインスタンスへの新しいルートを作成します。したがって、次のコレクションが発生した場合、インスタンスは実際にルート化され、コレクションの対象にはなりません。
このタフさには非常に注意する必要があります。オブジェクトが破棄されることを確認するためにファイナライザが使用される場合、破棄されたインスタンスが破棄された後に使用される場合、破棄されたインスタンスはObjectDisposedExceptionをスローする必要があると言うため、これは実際にプロトコルに違反します。
ガベージコレクターは、オブジェクトを3つのグループに分割します。
- 最後にルート化された参照がファイナライズキューの外側に存在するため、まだ生きているもの。
- ルート化された参照はどこにも存在しないため、削除する必要があります。
- ルート化された参照はファイナライズキューに存在するが、他には存在しないため、ファイナライズする必要があるもの。
所属していません StackOverflow