.NET垃圾收集

时间:2009-11-27 17:08:12

标签: c# .net garbage-collection

假设我有两个对象:

object1,object2

当我执行以下操作时:

object2.Foo = object1.Foo; //Edit: where Foo is a reference type

垃圾收集器做什么:

  1. 是否收集object1,同时持有分配给object2.Foo的值?
  2. 或者,object1是否会一直存在,直到收集到object2,因为object2.Foo引用了object1.Foo?
  3. 垃圾收集是否完全不同,如果是,请解释一下?
  4. 谢谢!

6 个答案:

答案 0 :(得分:6)

代码

object2.Foo = object1.Foo;

object1object2的状态没有影响。它可能对object2.Foo的旧值有影响。如果不存在对其的任何其他引用,则object2.Foo引用的对象现在可以是可收集的。

答案 1 :(得分:3)

假设Foo是具有后备存储的字段或属性,您将拥有一个类似于此的对象图(引用从左到右):

     object1
    /       \
root         foo
    \       /
     object2

如果你对object2的最后一次引用超出了范围,那么你就有了这个:

     object1
    /       \
root         foo
            /
     object2

根目录中的对象图中无法访问的任何内容都是垃圾收集的公平游戏,因此可以收集object2。但是,foo仍可通过object1访问,因此无法收集。

答案 2 :(得分:1)

如果没有对该对象的更多引用,它最终会收集对象1。 Foo与object1无关。如果Foo是一个引用对象,那么它存储在堆上,而object1恰好存储了一个指向Foo的指针。如果Foo是值类型,则在将其分配给object2时会生成副本,并且object1的Foo将与object1一起销毁。

当不再存在对象的引用时,某个对象会被销毁。收集类时销毁类中引用的对象的唯一情况是类是唯一指向特定引用的指针。

在下面的图片中,您会看到即使某些对象非常陈旧,也不会被收集,因为它们仍然被引用。然而,由于没有被引用,新创建的对象确实得到了GC。

alt text
(来源:chaoticjava.com

答案 3 :(得分:0)

您只是对Foo进行了另一次引用。这根本与object1无关。所有对object1的引用都超出范围后,将收集object1Foo完全单独收集。

编辑:当然假设foo是参考类型。

答案 4 :(得分:0)

Object2.FooObject1.Foo将引用同一个对象,即Object1.Foo最初指向的对象。以前由Object2.Foo引用的对象将在下次运行时由垃圾收集器收集(假设Foo的类型是类而不是结构)。

答案 5 :(得分:0)

这里的答案似乎错过了如果object1.foo曾经拥有一个对象(而不是一个空值),除非其他东西(object3.foo?)使用相同的对象,否则将会有什么垃圾收集。