哪些对象有资格进行垃圾回收?

Yip*_*Yay 12 c# garbage-collection weak-references

这是我最近在采访中被问到的一个问题:在"GC.Collect()"调用期间会收集哪些"随机"对象?

String a = new Random().Next(0, 1) ==1 ? "Whatever 1" : "Whatever 2";

String b = new WeakReference(new Random()).Target.Next(0, 1) == 1 ?
    "Whatever 1" : "Whatever 2";

GC.Collect();
Run Code Online (Sandbox Code Playgroud)

我回答说这是一个特定于实现的问题,它高度依赖于GC实现和相应的弱引用语义.据我所知,C#规范没有提供GC.Collect应该做什么以及如何处理弱引用的准确描述.

但是,我的采访者想听别的.

Mar*_*ell 13

这两个Random()实例WeakReference都有资格收集:

  • 第一个Random没有存储在本地,更不用说后来读取的本地.
  • 第二个Random被传递给了a WeakReference,所以无论如何都可以收集,但是它WeakReference 本身并不存在,所以它有资格收集.

没有字符串(这里只有2个字符串实例,而不是4个,即使达到了每个可能的代码路径):因为它们是c#代码中的文字,所以它们一旦存在就会被实现.

  • @MarcGravell - 但这是一个实现细节.当堆栈开始变得太深时,编译器会切换到本地.此外,您永远无法确定哪些堆栈值被视为垃圾,请记住GC看到JITted机器代码而不是IL. (3认同)
  • 如果编译器将它们放在堆栈或本地IL变量上,则运行时可能仍会看到引用.GC.Collect应该在调用站点之外发生,以便可预测. (2认同)

Zar*_*rat 9

确实,这是依赖于实现(和编译器)的.如果所有这些都采用相同的方法,则无法知道哪些对象仍在堆栈中.由于堆栈上的对象仍然被引用,因此它们不可收集.

面试官最想要你做的是在GC的调用下检查哪些对象仍然可以访问.Collect假设一个"完美"的实现,尽快丢弃所有内容.