【问题标题】:VB.NET - Should a Finalize method be added when implementing IDisposable?VB.NET - 实现 IDisposable 时是否应该添加 Finalize 方法?
【发布时间】:2010-09-11 21:54:30
【问题描述】:

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

  • disposedValue 成员变量
  • Sub Dispose() Implements IDisposable.Dispose
  • Sub Dispose(ByVal disposing As Boolean)

Dispose() 应该不用管,清理代码应该放在Dispose(disposing)

但是Dispose Finalize Pattern 表示您还应该覆盖Sub Finalize() 以调用Dispose(False)。为什么 IDE 也不添加这个?我必须自己添加它,还是以某种方式隐式调用?

编辑:知道为什么 IDE 会自动添加 80% 的所需内容,但忽略了 Finalize 方法?这种功能的全部意义不在于帮助您忘记这些事情吗?

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

【问题讨论】:

    标签: vb.net dispose idisposable destructor finalize


    【解决方案1】:

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

    如果您出于其他原因实施 IDisposable,则不需要实施 Finalize()。

    基本问题是这样的:如果没有调用 Dispose() 并且您的对象被垃圾回收,内存会泄漏吗?如果是,则执行 Finalize。如果没有,你不需要。此外,避免“仅仅因为它更安全”而实施 Finalize。具有自定义终结器的对象可能需要两次 GC 传递来释放它们——一次将它们放入待处理的终结器队列,第二次传递以实际释放它们的内存。

    【讨论】:

    • 实现 Dispose 并不意味着您也应该实现终结器。您可以在 Dispose 方法中释放非托管资源,而无需终结器。如果你必须实现一个终结器,你的实际清理逻辑应该在一个单独的函数中,该函数既可以处理也可以终结调用。
    • 这是不正确的。如果您仅依靠 Dispose() 来释放非托管资源,那么在未调用 Dispose 的情况下内存将泄漏。这正是终结器的用途。
    • 不知道为什么我之前没有回应 Scott 的评论——一定没有注意到,但 Laurent 是对的——如果您的 Dispose 正在清理非托管资源,那么为了安全起见,需要 Finalize。不要因为你很懒而放弃它。
    【解决方案2】:

    不,您不需要 Finalize,除非您有非托管资源需要清理。

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

    【讨论】:

    • 您可以在 Dispose 方法中释放非托管资源,而无需终结器。
    • 可以,但是如果没有调用 Dispose,那么你可能会在没有 Finalize 方法的情况下泄漏内存。
    【解决方案3】:

    正如其他人所说,您不需要实现终结器,除非您直接持有非托管资源。此外,假设您使用 .NET 2.0 或更高版本,您不太可能需要实现终结器,因为通常可以使用 SafeHandle 来包装您的非托管资源。

    不久前我写了一篇 fairly long blog post 介绍了 IDisposable 和终结器的背景和实现,如果您不完全清楚,可能值得一读。

    【讨论】:

    • 您可以在 Dispose 方法中释放非托管资源,而无需终结器。
    • 嗯,是的,这就是 IDisposable 模式的重点。但是,如果人们忘记调用 Dispose,那么终结器是一种最终清理它们的保护措施,因为它是由运行时调用的,所以不能忘记。
    【解决方案4】:
    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
    

    【讨论】:

    • 单块代码不是很有用。尝试更具建设性,在提供的代码背后有一个简短的描述和推理。
    猜你喜欢
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 2010-11-03
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多