c# – 方法本地.NET对象何时符合GC的条件?

假设我有一个这样的C#方法:(显然不是真正的代码)

byte[] foo()
{
    var a = MethodThatReturns500mbObject();
    var b = MethodThatReturns200mbObject(a);
    byte[] c = MethodThatReturns150mbByteArray(b);
    byte[] d = UnwiselyCopyThatHugeArray(c);
    return d;
}

正如你可以通过命名猜测的那样,这些方法返回的对象是巨大的.虽然前两个对象由数百万个较小的对象组成,而不是像后两个数组那样的大块,但每个RAM需要数百兆的RAM.

我们很快就会将其优化为流式处理解决方案,但与此同时,我想确保至少我们在执行代码生成后来的对象时不会阻止GC的早期对象.

我的问题是:一旦MethodThatReturns200mbObject(a)返回,对象是否有资格获得GC?如果没有,那么让GC知道有500MB存在等待它的最佳方法是什么?

我的问题的核心是.NET GC是否确定“此对象没有引用”是否足够聪明,知道在MethodThatReturns200mbObject(a)返回后无法引用.尽管var a在理论上仍然可用于以后的代码,但是在方法的第二行之下的任何地方都没有引用a.从理论上讲,编译器可以让GC知道a是未引用的.但在实践中,我不确定它是如何表现的.你知道吗?

最佳答案
This post explains it with examples.

从理论上讲,编译器可以让GC知道a是未引用的.但在实践中,我不确定它是如何表现的.你知道吗?

The correct answer is that it depends on the project configuration
whether the object will be eligible for garbage collection at the end
of the method. As discussed in When do I need to use GC.KeepAlive?
(which also describes the purpose of GC.KeepAlive – in short, it’s a
way of referencing or “using” a variable making sure that the
optimizer won’t optimize the usage away), the garbage collector might
decide to collect objects as soon as they are not usable by any
executing code anymore. This can very well happen in situations where
it would be valid to access a reference (at compile time), but no such
code has been written.

However, when compiling and executing code in Debug-mode, the compiler
prevents this from happening to ease debugging. As a result, the
correct implementation of our test method includes a preprocessor
directive:

另一个好读When do I need to use GC.KeepAlive?

点赞