您是否需要处理对象并将其设置为null,或者当它们超出作用域时,垃圾收集器将清理它们?


当前回答

通常,不需要将字段设置为null。然而,我总是建议丢弃非托管资源。

根据我的经验,我还建议你这样做:

如果不再需要,则取消订阅事件。 如果不再需要,将持有委托或表达式的任何字段设置为空。

我遇到过一些很难发现的问题,这些问题都是由于没有遵循上述建议而直接导致的。

Dispose()是执行此操作的一个好地方,但通常越快越好。

一般来说,如果存在对某个对象的引用,垃圾收集器(GC)可能要多花几代时间才能确定该对象不再使用。在此期间,对象始终保留在内存中。

这可能不是一个问题,直到你发现你的应用程序正在使用比你预期的更多的内存。当发生这种情况时,连接内存分析器来查看哪些对象没有被清理。将引用其他对象的字段设置为null并在处理时清除集合可以真正帮助GC确定可以从内存中删除哪些对象。GC将更快地回收使用的内存,使您的应用程序的内存需求更少,更快。

其他回答

通常,不需要将字段设置为null。然而,我总是建议丢弃非托管资源。

根据我的经验,我还建议你这样做:

如果不再需要,则取消订阅事件。 如果不再需要,将持有委托或表达式的任何字段设置为空。

我遇到过一些很难发现的问题,这些问题都是由于没有遵循上述建议而直接导致的。

Dispose()是执行此操作的一个好地方,但通常越快越好。

一般来说,如果存在对某个对象的引用,垃圾收集器(GC)可能要多花几代时间才能确定该对象不再使用。在此期间,对象始终保留在内存中。

这可能不是一个问题,直到你发现你的应用程序正在使用比你预期的更多的内存。当发生这种情况时,连接内存分析器来查看哪些对象没有被清理。将引用其他对象的字段设置为null并在处理时清除集合可以真正帮助GC确定可以从内存中删除哪些对象。GC将更快地回收使用的内存,使您的应用程序的内存需求更少,更快。

总是调用dispose。不值得冒这个险。大型托管企业应用程序应该受到尊重。不能做任何假设,否则它会反过来咬你一口。

别听她的。

很多对象实际上并没有实现IDisposable,所以你不必担心它们。如果他们真的超出了范围,他们将自动被释放。此外,我从来没有遇到过必须将某些内容设置为null的情况。

可能发生的一件事是,很多物体都可以保持打开状态。这将极大地增加应用程序的内存使用。有时很难判断这究竟是内存泄漏,还是您的应用程序只是在做很多事情。

内存配置文件工具可以帮助解决这类问题,但它可能很棘手。

此外,始终取消对不需要的事件的订阅。还要注意WPF绑定和控件。不常见的情况,但我遇到了这样的情况,我有一个WPF控件被绑定到一个底层对象。底层对象很大,占用了大量内存。WPF控件正在被一个新的实例所取代,而旧的实例由于某种原因仍然存在。这导致了一个大的内存泄漏。

在后台,代码写得很糟糕,但关键是你要确保没有使用的东西超出了范围。这需要很长时间才能用内存分析器找到,因为很难知道内存中的哪些东西是有效的,哪些不应该在那里。

在c#中,你永远不需要将对象设置为空。编译器和运行时将负责找出它们何时不再在作用域中。

是的,你应该处理实现IDisposable的对象。

当一个对象实现IDisposable时,您应该调用Dispose(在某些情况下,Close将为您调用Dispose)。

您通常不必将对象设置为null,因为GC将知道一个对象将不再使用。

当我将对象设置为空时,有一个例外。当我(从数据库中)检索了很多需要处理的对象,并将它们存储在一个集合(或数组)中。当“工作”完成时,我将对象设置为null,因为GC不知道我已经完成了对它的工作。

例子:

using (var db = GetDatabase()) {
    // Retrieves array of keys
    var keys = db.GetRecords(mySelection); 

    for(int i = 0; i < keys.Length; i++) {
       var record = db.GetRecord(keys[i]);
       record.DoWork();
       keys[i] = null; // GC can dispose of key now
       // The record had gone out of scope automatically, 
       // and does not need any special treatment
    }
} // end using => db.Dispose is called

如果对象实现了IDisposable,那么是的,你应该释放它。对象可能挂在本地资源(文件句柄、操作系统对象)上,否则这些资源可能不会立即释放。这可能导致资源短缺、文件锁定问题和其他本来可以避免的微妙错误。

参见在MSDN上实现一个Dispose方法。