GC根和局部变量

在查看Timer文档时,我使用以下注释运行了以下示例:

// Normally, the timer is declared at the class level, // so that it stays in scope as long as it is needed. // If the timer is declared in a long-running method, // KeepAlive must be used to prevent the JIT compiler // from allowing aggressive garbage collection to occur // before the method ends. You can experiment with this // by commenting out the class-level declaration and // uncommenting the declaration below; then uncomment // the GC.KeepAlive(aTimer) at the end of the method. //System.Timers.Timer aTimer; code in between // If the timer is declared in a long-running method, use // KeepAlive to prevent garbage collection from occurring // before the method ends. //GC.KeepAlive(aTimer); 

这是否意味着C#中的GC被允许垃圾收集局部变量,即使它有副作用? 大概是因为我之后再没有访问计时器,GC可以提前收集它吗?

如果我理解正确的话,我不确定我是这种优化的粉丝(但我可能不会这样做;))

是的,在最后一次使用变量之后,GC可能会在结束范围之前收集局部变量。 将GC.KeepAlive放在方法的末尾可确保变量在KeepAlive调用之前保持“活动”状态。

C#是命令式语言,所以GC的设计并不是为了解副作用。

据我了解GC,它将标记它认为在下一个GC循环期间不再需要作为垃圾收集候选者的任何变量或对象。 我不确定我是否理解这里的特定应用程序,但我确实知道有些情况下GC可能会在需要时标记要收集的资源(但由于编写代码的方式不会出现这种情况)。

通常,在方法期间,对象或变量在方法调用期间保持在范围内,但是如果方法调用持续时间长于GC循环之间的时间,则GC可能会将您的Timer对象视为超出范围并将其标记为收集。 添加GC.KeepAlive方法会强制GC等待该方法退出,然后再对Timer对象执行操作。