.net 实现IDisposable

.net 实现IDisposable,.net,vb.net,winforms,dispose,idisposable,.net,Vb.net,Winforms,Dispose,Idisposable,当我实现IDisposable时,VS会自动生成这些重新区域化的过程: #Region "IDisposable Support" Private disposedValue As Boolean ' To detect redundant calls ' IDisposable Protected Overridable Sub Dispose(disposing As Boolean) If Not Me.disposedValue Then

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

#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()

  • 我有一些字符串整数变量,它们不是一次性的,比如
    dim myVar as String=“value”
    ,那么在处理一次性对象时,如果我将这些变量的值设为空值会更好吗?像这样的

    sub dispose()
      myProcess.Dispose()
      myvar = nothing
    end sub
    
    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
    
  • 我的类调用一些WinAPI函数并重写WndProc子函数来解析消息,如果需要使用终结器,我需要使用终结器或SuppressFinalize。。。我需要做什么?我只是取消了Finalize子项的注释,就这样?。我不确定终结器的用途,也不确定何时以及如何使用它


虽然我不知道实现Dispose方法的正确方法,但我以这种方式处理它,但肯定在某种程度上是完全错误的…:

#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
我需要将myProcess.Dispose()放在上面代码的哪一行

没有。你没有。您应该做的是使用块创建类的任何实例作为
的一部分。这将在适当的时间自动调用
Dispose()
。否则,请始终将类创建为
try
块的一部分,并将其作为
finally
块的一部分调用
Dispose()

在处置一次性对象时,如果我将这些变量的值转换为空值,会更好吗

不,没有这个必要。字符串和int变量只使用内存,垃圾收集器将正确处理这些变量,而无需任何额外工作

我的类调用一些WinAPI函数并重写WndProc子函数来解析消息,如果需要使用终结器,我需要使用终结器或SuppressFinalize。。。我需要做什么

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

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

' 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 state”)完全没有价值,因为您永远无法单独处置托管状态。这完全取决于垃圾收集器。考虑到这一点,您可以完全删除该条件。我发现这个规则的唯一例外是事件处理程序。您可以使用此位置取消订阅班级中的任何学员

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

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

我需要将myProcess.Dispose()放在上面代码的哪一行

没有。你没有。您应该做的是使用
块创建类的任何实例作为
的一部分。这将在适当的时间自动调用
Dispose()
。否则,请始终将类创建为
try
块的一部分,并将其作为
finally
块的一部分调用
Dispose()

在处置一次性对象时,如果我将这些变量的值转换为空值,会更好吗

不,没有这个必要。字符串和int变量只使用内存,垃圾收集器将正确处理这些变量,而无需任何额外工作

我的类调用一些WinAPI函数并重写WndProc子函数来解析消息,如果需要使用终结器,我需要使用终结器或SuppressFinalize。。。我需要做什么

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

因此,在实现IDisposable时,大多数时候您只需要关注该示例中的第一个方法。你可能还想解缆