VB.NET-在实现IDisposable时是否应该添加Finalize方法?

时间:2020-03-06 14:31:28  来源:igfitidea点击:

在Visual Studio中,当我键入"Implements IDisposable"行时,IDE会自动添加:

  • 一个disposedValue成员变量
  • Sub Dispose()实现IDisposable.Dispose
  • Sub Dispose(ByVal以布尔方式进行处理)

应该将Dispose()保留下来,并将清理代码放入Dispose(dispose)中。

但是Dispose Finalize Pattern表示我们还应该重写Sub Finalize()来调用Dispose(False)。为什么IDE也不添加此内容?我必须自己添加它,还是以某种方式隐式调用它?

编辑:知道为什么IDE会自动添加80%的所需内容,却忽略了Finalize方法吗?难道不是这种功能的全部目的就是要不要忘记这些东西吗?

EDIT2:谢谢大家的出色回答,现在这很有意义!

解决方案

如果我们实际上持有的非托管资源将不会被垃圾收集器自动清理,并在Dispose()中清理这些资源,那么可以,我们应该在Finalize()中执行相同的操作。

如果由于其他原因要实现IDisposable,则不需要实现Finalize()。

基本问题是这样的:如果未调用Dispose()并收集了对象垃圾,会发生内存泄漏吗?如果是,请执行Finalize。如果不是,则不需要。另外,请避免仅出于"更安全"而实施Finalize。具有自定义终结器的对象可能需要两次GC释放才能释放它们-一次将它们放置在挂起的终结器队列中,而第二次释放则实际上释放它们的内存。

不,除非我们有非托管资源需要清理,否则不需要Finalize。

在大多数情况下,类为可抛弃型的原因是因为它保留了对其他托管IDisposable对象的引用。在这种情况下,不需要或者不需要Finalize方法。

正如其他人所说,除非直接持有非托管资源,否则无需实现终结器。另外,假设我们在.NET 2.0或者更高版本中工作,则不太可能不需要实现终结器,因为通常可以使用SafeHandle来包装非托管资源。

我写了一篇相当长的博客文章,其中介绍了IDisposable和finalizers的背景和实现,如果我们不太清楚,那么可能值得一读。

Implements IDisposable

Public Overloads Sub Dispose() Implements IDisposable.Dispose

    Dispose(True)
    GC.SuppressFinalize(Me)

End Sub

Protected Overloads Sub Dispose(ByVal disposing As Boolean)

    If disposing Then
        ' Free other state (managed objects).
    End If
    ' Free your own state (unmanaged objects).
    ' Set large fields to null.
End Sub

Protected Overrides Sub Finalize()

    Dispose(False)
    MyBase.Finalize()

End Sub