私の理解では、GC がメイン グラフから (強い参照を介して) アクセスできなくなったオブジェクトのサブグラフを見つけると、それらを収集してメモリを再利用します。私の質問は、アクセスできないオブジェクトが削除される順序に関するものです。これはアトミック操作として発生しますか? アクセスできないオブジェクトはすべて一度にファイナライズされますか?それとも、GC はアプリケーションの実行中に各オブジェクトを 1 つずつファイナライズしますか? オブジェクトが 1 つずつファイナライズされる場合、従う特定の順序はありますか?
オブジェクト B への弱い参照を保持するオブジェクト A がある場合、B のインスタンス メソッドを呼び出す前に、A が B がまだ生きているかどうかを確認する必要があることは明らかです。ここで、B が別のオブジェクト C への強い参照を保持しているとします。B がまだ生きている場合、C もまだ生きていると常に保証されますか? GC がコレクションのために B と C の両方をマークした可能性はありますが、C は B の前にファイナライズされますか?
私の推測では、B から C にアクセスすることは常に安全であると思います (これは強力なリファレンスであるため)。しかし、私が間違っていると、非常に断続的な追跡困難なバグが発生する可能性があるため、この仮定を確認したいと思います。
public class ClassA
{
private readonly WeakReference objBWeakRef;
public ClassA(ClassB objB)
{
objBWeakRef = new WeakReference(objB);
}
public void DoSomething()
{
// The null check is required because objB
// may have been cleaned-up by the GC
var objBStrongRef = (ClassB) objBWeakRef.Target;
if (objBStrongRef != null)
{
objBStrongRef.DoSomething();
}
}
}
public class ClassB
{
private readonly ClassC objCStrongRef;
public ClassB(ClassC objC)
{
objCStrongRef = objC;
}
public void DoSomething()
{
// Do I also need to do some kind of checking here?
// Is it possible that objC has been collected, but
// the GC has not yet gotten around to collecting objB?
objCStrongRef.DoSomething();
}
}
public class ClassC
{
public void DoSomething()
{
// do something here... if object is still alive.
}
}