首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现IDisposable

实现IDisposable
EN

Stack Overflow用户
提问于 2013-11-10 22:09:01
回答 1查看 1.6K关注 0票数 1

当我实现IDisposable时,VS会自动生成这些区域化过程:

代码语言:javascript
复制
#Region "IDisposable Support"
    Private disposedValue As Boolean ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: dispose managed state (managed objects).
            End If

            ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
            ' TODO: set large fields to null.
        End If
        Me.disposedValue = True
    End Sub

    ' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
    'Protected Overrides Sub Finalize()
    '    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

假设我的类有一个从未关闭/释放的一次性对象(来自Process的一个新进程),所以我想在类上实现IDisposable .

我的问题是:

  • 在上面的代码的的哪一行中,我需要放置一个myProcess.Dispose()
  • 我有一些字符串Integer变量,这些变量不是一次性的,比如dim myVar as string = "value",那么如果我在释放可弃对象时将这些var的值转换为空值更好呢?像这样吗?: sub () myProcess.Dispose() myvar = nothing end sub
  • 我的类调用一些WinAPI函数并重写WndProc子来解析消息,我需要使用终结器或者可以使用SuppressFinalize?,如果我需要使用终结器.我需要做什么?我只是取消对最后的潜艇的评论,就这样?我不确定终结器的用途,也不确定何时和如何使用它。

虽然我不知道实现Dispose方法的确切方法,但我以这种方式处理它,但肯定在一种或另一种方式上完全错误:

代码语言:javascript
复制
#Region " Dispose "

    ''' <summary>
    ''' Disposes all the objects created by this class.
    ''' </summary>
    Public Sub Dispose() _
    Implements IDisposable.Dispose

        ' Process
        p.Dispose() 

        ' Public Properties
        Me.mp3val_location = Nothing
        Me.CheckFileExist = Nothing

        ' String variables
        StandardError = Nothing
        StandardOutput = Nothing
        Info = Nothing
        Warnings = Nothing
        Errors = Nothing
        Tags = Nothing

        ' RegEx variables
        Info_RegEx = Nothing
        Warning_RegEx = Nothing
        Fixed_RegEx = Nothing

        ' EventArgs Variables
        StartedArgs = Nothing
        ExitedArgs = Nothing

        GC.SuppressFinalize(Me)

    End Sub

#End Region

更新

所以..。简化与生成的代码之间的混淆,以便更直观、更友好地处理请求,我应该这样使用它吗?:

代码语言:javascript
复制
Public Class Test : Implements IDisposable

Public Sub Dispose() Implements IDisposable.Dispose
    Dispose(True)
    GC.SuppressFinalize(Me)
End Sub

Protected Overridable Sub Dispose(IsDisposing As Boolean)

    Static IsBusy As Boolean ' To detect redundant calls.

    If Not IsBusy AndAlso IsDisposing Then

        ' Dispose processes here...
        ' myProcess.Dispose()

    End If

    IsBusy = True

End Sub

End Class
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-11-10 22:34:41

在上面的代码的哪一行中,我需要放置一个myProcess.Dispose()

没有。您应该做的是创建类的任何实例,作为using块的一部分。这将在适当的时间自动调用Dispose()。如果失败,始终将类创建为try块的一部分,并调用Dispose()作为finally块的一部分。

当我释放一次性对象时,如果我将这些var的值转换为空值,会更好吗?

不是的。没有必要这样做。String和int变量只使用内存,垃圾收集器将正确处理这些变量,而不需要任何额外的工作。

我的类调用一些WinAPI函数并重写WndProc子来解析消息,我需要使用终结器或者可以使用SuppressFinalize?,如果我需要使用终结器.我该怎么办?

如果WinAPI调用分配任何系统资源(如文件句柄、gdi句柄、线程、套接字等)、,则需要一个终结器,如果这些资源不是现有.Net类的一部分,则该类将为您处理释放这些资源的问题。只有当这两种条件都为真时,您才需要一个终结器。通常,终结器只会调用.Dispose(False)方法,如注释的示例所示,因此您的清理代码只需要驻留在一个地方。

因此,在实现IDisposable时,大多数情况下只需要关注该示例中的第一个方法。您还可能希望取消对Finalize()方法的注释,但仅此而已。现在让我们看看这个方法:

代码语言:javascript
复制
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
    If Not Me.disposedValue Then
        If disposing Then
            ' TODO: dispose managed state (managed objects).
        End If

        ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
        ' TODO: set large fields to null.
    End If
    Me.disposedValue = True
End Sub

这里的诀窍是TODO的评论令人困惑..。甚至是误导。第一个注释("dispose managed“)是完全没有价值的,因为您永远无法单独处理托管状态。这完全取决于垃圾收集器。考虑到这一点,您可以完全删除该条件。对于此规则,我发现的唯一例外是事件处理程序。您可以使用此位置取消订阅类中的任何委托。

第二个TODO注释(“空闲的非托管资源”)更有用。它将告诉您在何处放置非托管资源的清理代码。只是持续太久了。如果它在第一个短语之后停止,它就会更清楚。如果类本身封装了任何IDisposable类的实例,那么这是为对象调用.Dipose()的好地方。

第三个TODO注释(“将大字段设置为空”)也在很大程度上没有必要。它通常无助于在.Net中将项设置为NULL。在这种情况下,您已经在处理对象了。这意味着它很可能会超出范围,而且这些对象在下次运行GC时仍然有资格进行收集。这样做的唯一原因是,如果您怀疑您的对象在释放后不久不会超出范围。在这种情况下,将这些字段设置为null可能允许更早地收集较大的内存块.但是,这种情况将是您类的用户设计不善的一个症状。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19895856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档