0

「クラスa」を指す「参照クラス」(参照クラスbと呼びましょう)を含むクラス(クラスaと呼びましょう)があります。

これにより、ループ接続が作成されます。「クラス a」および「参照クラス b」への他のすべての参照が削除されても、それらを参照するクラスが引き続き存在します。C# のガベージ コレクションは、この内部ループのみを検出するのに十分強力ですか? または、収集する前に何らかの方法でそのリンクを切断する必要があります (すべての外部リンクが切断されると、これは不可能になります)。

2 つが相互に参照し続ける方法については、次のコード例を参照してください。

Public Class ClassA
{
    Private ReferenceClassB reference;
    Public ClassA()
    {
        reference = new ReferenceClassB(this);
    }

}

Public Class ReferenceClassB
{
    Private ClassA referencedClass;
    Public ReferenceClassB(ClassA reference)
    {
        referencedClass = reference;
    }
}

上記の 2 つのクラスを使用すると、ClassA のバージョンが外部に作成されてから null に設定された場合でも、そのオブジェクトへの参照が引き続き存在し、作成された ReferenceClassB オブジェクトにも同様に参照が存在します。しかし、これらのオブジェクトは「メイン プログラム」に接続されていないため、理論的にはガベージ コレクターがクリーンアップしても安全ですが、実際の実装はそれらを取り除くのに十分スマートですか?

4

1 に答える 1

2

はい、ガベージ コレクターは循環参照を処理します。スタックオーバーフローでこの質問を確認してください。

アップデート:

次のコードを使用してテストできます。

public class ClassA
{
    private ReferenceClassB reference;
    public ClassA()
    {
        reference = new ReferenceClassB(this);
    }

}

public class ReferenceClassB
{
    private ClassA referencedClass;
    public ReferenceClassB(ClassA reference)
    {
        referencedClass = reference;
    }
}
class Program
{
    static void Main(string[] args)
    {
        ClassA a = new ClassA();
        ReferenceClassB b = (ReferenceClassB) a.GetType().GetField("reference", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(a);
        WeakReference weakA = new WeakReference(a);
        WeakReference weakB = new WeakReference(b);
        a = null;
        b = null;
        GC.Collect();
        Debug.Assert(weakA.IsAlive==false);
        Debug.Assert(weakB.IsAlive==false);
    }
}
于 2013-08-25T16:18:53.227 に答える