C#:在什么情况下应该清空引用?
CLR 探查器还可以揭示哪些方法分配的存储空间超出您的预期,并且可以发现您无意中保留对无用对象图的引用的情况,否则这些对象图可能会被 GC 回收。 (一个常见的问题设计模式是软件缓存或不再需要的项目的查找表,或者以后可以安全地重建。当缓存在其使用寿命结束后使对象图保持活动状态时,这是悲剧性的。相反,一定要清空对不再需要的对象的引用。) -- 写入速度更快托管代码
我认为我以前从未真正取消过引用。我认为您并不总是需要这样做,但我想有时记住这样做也很重要。但是,那是什么情况呢?什么时候应该取消引用?
The CLR Profiler can also reveal which methods allocate more storage than you expected, and can uncover cases where you inadvertently keep references to useless object graphs that otherwise could be reclaimed by GC. (A common problem design pattern is a software cache or lookup table of items that are no longer needed or are safe to reconstitute later. It is tragic when a cache keeps object graphs alive past their useful life. Instead, be sure to null out references to objects you no longer need.) -- Writing Faster Managed Code
I don't think I've really ever nulled out a reference before. I assume you don't always need to do this, but I guess there also are times when it is important to remember to do it. But, what cases is that? When should you null out references?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
仅当保存引用的变量将保持“活动”状态但您不希望引用本身阻止垃圾收集时,才需要执行此操作。换句话说,如果对象 A 持有对对象 B 的引用,并且您不再需要 B 了,但 A 将由于其他原因而保持活动状态。另一个常见的例子是静态变量,只要 AppDomain 存在,它们就“有效”。
对于局部变量,它几乎不需要,因为GC可以检测代码中访问变量的最后一个可能的点。但是,如果您在第一次迭代期间使用在循环外部声明的变量,但您知道后续迭代中不需要它,则可以将其设置为 null 以帮助对象符合条件GC 较早。
根据我的经验,我很少遇到这种情况。我几乎不会为了 GC 而故意将变量设置为 null。通常,对象内的所有成员变量都是“有用的”,直到该对象本身符合 GC 条件。如果您发现自己的成员变量对于对象的整个生命周期没有用处,您可能想看看这是否表明设计存在问题。
You only need to do it when the variable holding the reference is going to stay "alive" but you don't want the reference itself to prevent garbage collection. In other words, if object A holds a reference to object B, and you don't need B any more but A will stay alive for other reasons. Another common example is static variables, which are "alive" for as long as the AppDomain is.
For local variables it's almost never needed, because the GC can detect the last possible point in code where a variable will be accessed. However, if you use a variable declared outside a loop during the first iteration, but you know you won't need it for subsequent iterations, you could set that to null to help the object to become eligible for GC earlier.
In my experience it's very rare to find myself in this situation. I hardly ever deliberate set variables to null for the sake of the GC. Usually all the member variables within an object are "useful" until the object itself becomes eligible for GC. If you find yourself with member variables which aren't useful for the whole lifetime of the object, you might want to see whether that indicates a problem with the design.
如果您有长期存在的对象(如引用中的缓存示例)保存对短期对象(如缓存项)的引用,这一点很重要。长寿命对象的其他示例可以是单例对象、Windows 窗体应用程序中的主窗体实例、ASP.NET 应用程序的应用程序实例等。
我想添加另一个常见的坑:订阅由长寿的物体。由于事件发布者持有对所有订阅者的引用,因此如果您不取消订阅,则不会收集订阅者(例如仅需要几毫秒的 ASP.NET 页面或控件实例)。
It's important if you have long lived objects (like the cache example in your quote) holding references to short lived objects (like the cache items). Other examples of long lived objects could be singleton objects, the Main Form instance in a Windows Forms application, the Application instance of a ASP.NET application etc.
I would like to add a another common pitfull: short lived objects subscribing to events published by long lived objects. As the event publisher holds a reference to all subscribers, the subscribers (like e. g. ASP.NET page or control instances that are needed only for milliseconds) won't be collected if you do not unsubscribe.
当您知道不再需要的对象的引用不会被垃圾收集时,您应该将它们的引用清空。
如果您有Effective Java一书,请查看第5项,其中有一个示例由于对象引用未清空,因此存在内存泄漏的堆栈实现。如果您没有该书,可以在 Google 图书上查找该部分 此处。
You should null out references for object you don't need anymore when you know they won't be garbage collected otherwise.
If you have Effective Java book, look at Item 5, there is an example of a stack implementation that has memory leaks because the objects references are not nulled out. If you don't have that book, you can look that part on Google Books here.