C#: 在哪些情况下应该将引用设置为null?

11
CLR Profiler可以揭示哪些方法分配的存储空间超出了您的预期,并且可以发现您意外地保留了对无用对象图的引用,否则这些对象图本应该被GC回收。(一个常见的设计模式问题是软件缓存或查找表中包含不再需要或安全重新构建的项目。当缓存使对象图在其有用寿命之后仍然存活时,这是令人遗憾的。相反,请确保将不再需要的对象引用设置为null。)--编写更快的托管代码 我从来没有设置过对象引用为null。我认为你并不总是需要这样做,但我猜也有重要的时候需要记得这样做。那么,什么情况下需要这样做呢?何时应该设置对象引用为null?
3个回答

11

只有在保存引用的变量需要“存活”,但是您不希望引用本身阻止垃圾回收时,才需要这样做。换句话说,如果对象A持有对对象B的引用,而您不再需要B,但A因其他原因仍将保持活动状态。另一个常见的例子是静态变量,它们在AppDomain存在期间一直“存活”。

对于局部变量,几乎不需要这样做,因为GC可以检测代码中变量最后可能被访问的时刻。但是,如果您在第一次迭代期间使用在循环之外声明的变量,但知道在随后的迭代中不需要它,则可以将其设置为null,以帮助对象更早地变为可回收状态。

根据我的经验,我很少遇到这种情况。我几乎从不会为了垃圾回收而故意将变量设置为null。通常,对象内的所有成员变量在对象本身变为可回收之前都是“有用”的。如果发现自己有在整个对象生命周期内有用的成员变量,则可能需要查看设计是否存在问题。


有道理。我想我也差不多是这样做的,只是没有真正考虑过。 - Svish

4

如果你有长生命周期的对象(比如你引用中的缓存示例),它持有对短生命周期对象(比如缓存项)的引用,这点很重要。其他一些长生命周期对象的示例可能包括单例对象、Windows Forms应用程序中的主窗体实例、ASP.NET应用程序的应用程序实例等。

我想再提一个常见的陷阱:短生命周期对象订阅由长生命周期对象发布的事件。由于事件发布者持有对所有订阅者的引用,如果你不取消订阅,那么像ASP.NET页面或控件实例之类只需要存在毫秒级别的订阅者将无法被回收。


一个特别恶劣的例子是 Windows Forms 中的主题控件(例如 ToolStrip),它们在变为可见时会向 Windows 主题更改事件注册,并且如果您在取消引用之前不将 Visible 设置为 false,则不会注销自己。如果您的应用程序创建和销毁大量这些对象,可能会遇到麻烦 - 特别是如果您期望这些控件持有引用的对象也将被垃圾回收。每当涉及此问题时,我都会拿出这个例子,因为它非常令人痛苦。 - Robert Rossney

1

当你知道某些对象不会被垃圾回收时,应该将其引用设置为 null。

如果你有Effective Java这本书,可以看看第5条建议,其中有一个栈实现的例子,因为对象引用没有被设置为 null 而导致内存泄漏。如果你没有这本书,可以在 Google Books 这里查看相关部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接