【发布时间】:2017-06-26 19:38:13
【问题描述】:
假设一个函数接受一个对象列表:
void WriteData(List<LargeObject> objectsToWrite);
如果我们调用这个函数,为了可读性或调试,我们可能会考虑将其设为局部变量:
var objectsToWrite = SomeMethodThatPreparesTheObjects();
WriteData(objectsToWrite);
但是,我们也可以内联变量,使得函数调用变为:
WriteData(SomeMethodThatPreparesTheObjects());
这两者在功能上是等效的——但我的问题是:这两种方法是否都保留对象列表直到方法执行结束(因为有一个局部变量将是 GC 根)——或者它是否取决于编译器内部关于后一个调用是否最终被翻译成局部变量?
【问题讨论】:
-
列表(或任何对象)将存储在堆上。它与您如何编写代码无关,无论您使用字段、变量还是内联函数。
-
局部变量不会阻止对象被收集。当不再使用该变量时 - 可以收集对象,甚至在方法完成之前。因此,在方法执行结束之前,您使用的任何方法都不会保留对象。
-
请注意,在某些情况下您希望一个对象保持活动状态;正如上面的评论正确指出的那样,优化器可以提前杀死本地人。如果您必须保持本地活动,请使用
KeepAlive函数。有关详细信息,请参阅stackoverflow.com/a/15388788/88656。 -
另请注意,还有第三个选项:
WriteData(objectsToWrite: SomeMethodThatPreparesTheObjects());这会生成与WriteData(SomeMethodThatPreparesTheObjects());相同的IL。 -
@EricLippert - 感谢您的链接 - 这非常有帮助
标签: c# garbage-collection