垃圾收集:是否有必要在 Dispose 方法中将大对象设置为 null?
-
09-06-2019 - |
题
是否需要设置大物体 null
当实施一个 Dispose()
方法?
解决方案
通常不会。
垃圾收集器会查找有根对象,并且如果两个对象都不是有根对象,则循环依赖项不会阻止收集。
有一个警告:如果对象 A 引用了对象 B,并且对象 B 正在被释放,您可能需要清理该关系,否则可能会导致泄漏。此表面最常见的位置是在事件处理程序中(从 A->B 的引用是 B 控制的引用,因为它订阅了 A 上的事件)。在这种情况下,如果 A 仍然是 root,则即使 B 已被释放,也无法被收集。
其他提示
如果类具有 Dispose 方法,最佳实践是调用它。其背后的原因是,在调用时处置运行,而将对象设置为null只需在GC中的最终队列中添加一个条目,而我们无法确定GC何时运行。
在仅使用托管资源(例如数组)的类型上实现 Dispose 方法不会带来性能优势,因为它们会被垃圾收集器自动回收。主要对使用本机资源的托管对象和公开给 .NET Framework 的 COM 对象使用 Dispose 方法。使用本机资源的托管对象(例如 FileStream 类)实现 IDisposable 接口。
已采用的调用 Dispose 的一种优雅方法是使用“using”结构。对于那些可能不熟悉该构造的人来说,它提供了一种在实现 IDisposable 的实例上隐式调用 Dispose() 的方法,即使在操作期间抛出异常也是如此。以下是 using 构造的示例:
using(DisposableClass dc = new DisposableClass())
{
dc.PerformActionOnUmanagedResources();
dc.PerformAnotherActionOnUmanagedResources();
}
在前面的示例中,如果 PerformActionOnUmanagementResources() 方法中引发异常,尽管不会处理 PerformAnotherActionOnUmanagementResources() 方法,但 using 块仍会隐式调用 dc 上的 Dispose 方法,以确保释放任何非托管资源。
dispose 方法的目的是通过调用基类 dispose 方法来释放与您的类以及父类关联的所有资源。阅读此链接,它应该会让事情变得更清楚一些:
“大物体”是什么意思?
不过,您至少应该对任何实现 IDisposable 的成员调用 Dispose()。
正如其他人指出的那样,这不是必需的,但这是很好的做法,有助于调试。
一旦对象完成了它正在使用的指针,那么将其设置为 null 有助于防止以后重用该对象(您将得到空引用异常)。
删除成员指针后,同样的逻辑也适用于在 C++ 析构函数中将成员指针设置为 null。没有 需要 这样做,但这有助于以后排除故障。
思考一下 Disposable 方法的用途:这通常是因为您持有一些在垃圾收集期间不会释放的资源。这通常类似于数据库连接或文件句柄。因此,一旦调用 Dispose 方法,所有这些资源都已被释放。
我认为空值漂浮比“僵尸”物体漂浮更有害。