2013-08-25 1 views
0

У меня есть класс (позволяет назвать его классом a), который содержит «ссылочный класс» (позволяет назвать его ссылочным классом b), который указывает на «класс a».Может ли сборник мусора на C# найти и удалить только связанные классы?

Это создает соединение цикла, если все другие ссылки на «класс a» и «ссылочный класс b» будут отброшены, они все равно будут иметь классы, ссылающиеся на них. Является ли сборка мусора на C# достаточно сильной, чтобы обнаружить только этот внутренний цикл или мне нужно как-то сломать эту ссылку, прежде чем они будут собраны (как только все внешние ссылки будут разбиты, это будет невозможно)

См. Следующий пример кода как они продолжают ссылаться друг на друга.

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 производится внешней, а затем установить на нуль, есть еще ссылка на этот объект, и также с созданным объектом ReferenceClassB. Но эти объекты не будут связаны с «основной программой», поэтому теоретически они безопасны для уборщика мусора, но является ли реальная реализация достаточно умной, чтобы избавиться от них?

+0

Да, GC может это сделать. В C++ .NET есть специальные классы для такого рода ссылок, но в C# он работает. – user35443

+0

Спасибо вам обоим, ответил на мой вопрос и дал мне лучшее понимание того, что еще может вызвать проблемы. В моей текущей реализации он будет «деиндинироваться» из основной программы (root) и из-за этого будет собран. – Taoh

ответ

2

Да, сборщик мусора обрабатывает круглые ссылки. проверьте этот question на stackoverflow.

UPDATE:

вы можете проверить, что, используя следующий код:

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); 
    } 
} 
+2

Это должно было быть просто комментарием или закрытым голосованием, ИМО. –