垃圾收集器和循环引用

Naw*_*waz 57 c# garbage-collection circular-reference

考虑这两个类:

public class A
{
     B b;
     public A(B b) { this.b = b; }
}

public class B
{
     A a;
     public B() { this.a =  new A(this); }
}
Run Code Online (Sandbox Code Playgroud)

如果我有类似上面设计的类,那么垃圾收集器(GC)会收集这些类的对象吗?

假设我这样做:

void f()
{
     B b = new B();
}
Run Code Online (Sandbox Code Playgroud)

在这个方法中,我创建了一个B被调用的实例b,当方法返回时,b超出范围,GC应该能够收集它,但是如果它要收集它,它必须先收集a它是成员的B,并收集a,它需要收集b第一是的构件A.它变成了圆形.所以我的问题是:这样的循环引用会阻止GC收集对象吗?

  • 如果是,那我们怎样才能避免这个问题呢?我们怎样才能确保在课堂设计中没有循环参考?是否有任何工具(或编译器选项)可以帮助我们检测循环引用?
  • 如果没有,我们在哪里和为什么使用WeakReference课程?它的目的是什么?

Jar*_*Par 90

.Net垃圾收集器绝对可以处理循环引用.垃圾收集器如何工作的非常高级别的视图是......

  • 从本地,静态和GC固定对象开始.这些都不能收集
  • 通过遍历这些对象的子项来标记可以到达的每个对象
  • 收集每个未标记的对象.

这允许收集循环引用就好了.只要从已知无法收集的对象中找不到它们,那么循环引用基本上是无关紧要的.

注意:我意识到我遗漏了许多有趣的细节,以便简单而直接地回答这个问题

  • 这不是计算成本很高吗 (2认同)

Har*_*san 31

不,这不会有问题,因为GC可以处理循环引用

MSDN说

如果一组对象包含彼此的引用,但这些对象中没有一个直接或间接地从堆栈或共享变量引用,则垃圾收集将自动回收内存.


dri*_*iis 5

没有那个循环引用不会影响垃圾收集器,它将完全能够收集B的实例.

垃圾收集器知道没有人可以在超出范围后引用B的实例,因此,没有人可以使用B的实例来间接引用A.


mfe*_*old 5

几个答案已经解释了循环引用不是问题.

至于弱引用 - 使用它们的原因是缓存.

当GC遍历对象依赖树时,他忽略了弱引用.换句话说,如果对象的唯一引用是弱对象,则它将被垃圾收集,但如果在引用创建和您尝试使用之间没有垃圾收集,您仍然可以访问该对象.