圆形引用对象的垃圾收集

时间:2013-05-16 18:54:21

标签: c# .net garbage-collection clr

假设我有2个对象 - 对象A和对象B.对象A引用对象B,对象B引用对象A.

  1. 如果对象A和A都是对象B不在代码的引用范围内 - 垃圾收集器如何知道它可以被收集。
  2. 垃圾收集器如何推断出任何对象超出范围/为垃圾收集做好准备?
  3. 如果对象A不是由我们的代码引用但仍然可以是独立的,那该怎么办?例如。如果它是一个Form类,那么即使Object A被重新初始化为一个新实例或指定为null,它也可以独立运行。

2 个答案:

答案 0 :(得分:6)

  1. GC不会选择一个对象并查看是否有任何对象引用它;保持它,如果它。 GC有一个它知道“活着”的每个对象的集合。此集合以所有静态变量,堆栈上的所有变量以及一些其他特殊情况开始。然后它会遍历每个“活着”的对象并查看它们引用的对象。每个引用的对象本身都标记为“活动”,因为它意味着它可以通过另一个活动对象以某种方式到达。它会重复此过程,直到找不到新对象。然后,任何未被标记为活着的东西都是无法到达的。正如您所知,由于您从未检查任何给定的“死”对象引用的内容,因此无论是否存在循环引用都无关紧要。

  2. 见#1。

  3. 嗯,在大多数情况下,它实际上是在某处引用的;例如,对于表单,您Application.OpenForms引用任何打开的表单。对于诸如这些的对象,通常存在类似的构造。在极少数情况下,如计时器这样的对象,GC会明确告知它们不会被收集。这种情况非常罕见,您通常无需担心这些情况。

答案 1 :(得分:0)

  1. 垃圾回收器会查看活动引用,并且可以收集从那里找不到的任何内容。这样两个对象相互引用并不重要,因为这两个引用都是不活动的。

  2. 见1.

  3. 表单是一个组件,因此通过注册为一个表单来保持活动状态。初始化后,应用程序本身会保持活动状态,直到表单被处理完毕。拥有一个引用表单然后将变量设置为null的变量只会更改引用,它不会对对象本身做任何事情。