在没有引用的情况下处理 IDisposable

Disposing of IDisposable Without Reference

有时会使用实现 Dispose() 的 class 的实例,但实际上并未保留对该实例的任何引用。

这种情况下垃圾回收应该怎么办?

示例:

MsgBox(New System.Net.WebClient().DownloadString("http://www.website.com"))

WebClient 实施 Dispose().

请随意重命名主题。

在这里,您应该重构代码以便进行处置。由于 Using 声明,这非常容易。

我现在知道为什么 WebClient 需要处理了。据我所知,在简单的用例中,它不会占用任何资源。

此问题与GC无关。当 GC 发现它未被引用时,该对象将像任何其他对象一样被清理。

只有在极少数情况下,正确编写的代码才能允许放弃对资源持有对象的所有引用,而无需首先调用它 Dispose。除了延迟清理导致的问题之外,IDisposable 对象的粗心处理在某些情况下也会导致 提前 清理。

例如,假设一个 class Widget 使用某种本机句柄 Widget,并且它有一个方法

void Woozle()
{
  NativeWidget.Woozle(myWidget));
}

如果在放弃之前用 Widget 完成的最后一件事是调用 Woozle,GC 可能会注意到它获取了 myWidget、[=42 的值=] 的字段 Widget 可以再次访问,因此如果它消失,没有人会注意到。因为垃圾收集是一个异步过程,所以即使 Woozle 方法是 运行,也可能会发生这种情况 。如果 Widget 有释放 myWidget 资源的析构函数或 Finalize 方法,结果可能是灾难性的。

相比之下,如果 Widget 引用是为了在其上调用 Dispose 而保留的,并且 Dispose 执行 GC.SuppressFinalizeGC.KeepAlive,那么在对 Woozle 的调用完成之前,终结器 运行 是不可能的。