实施IDisposable [英] Implementing IDisposable

查看:78
本文介绍了实施IDisposable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我实现IDisposable时,VS自动生成以下区域化过程:

  #Region IDisposable支持 
私有处置值作为布尔值'要检测冗余呼叫

'IDisposable
受保护的可覆盖子处置(以布尔值处置)
如果不是Me.disposedValue然后
如果处置则
'TODO:处置托管状态(托管对象)。
End if

’TODO:释放非托管资源(非托管对象)并覆盖下面的Finalize()。
’TODO:将大字段设置为null。
End如果
Me.disposedValue = True
End Sub

'TODO:仅当上述Dispose(ByVal as Boolean布尔值)具有释放代码时,才覆盖Finalize()非托管资源。
’Protected Overrides Sub Finalize()
’’请勿更改此代码。将清除代码放在上面的Dispose(ByVal以Boolean方式放置)中。
’Dispose(False)
’MyBase.Finalize()
’End Sub

’Visual Basic添加此代码以正确实现一次性模式。
Public Sub Dispose()实现IDisposable.Dispose
’请勿更改此代码。将清除代码放在上面的Dispose(以Boolean方式处理)中。
处置(真实)
GC.SuppressFinalize(Me)
结束子
#结束区域

想象一下,我的班级有一个一次性对象(流程类中的新流程),它永远不会关闭/处置,所以我想处置它,以在类上实现IDisposable ...

我的问题是:




  • 在哪一行完全相同上面的代码,我需要放入 myProcess.Dispose()


  • I有一些 String Integer 变量不是一次性的,例如 dim myVar as string = value ,然后放置一次性对象时将这些var的值转换为null会更好吗?像这样吗?:

      sub dispose()
    myProcess.Dispose()
    myvar = none
    end sub


  • 我的类调用了一些WinAPI函数,并且还将WndProc子函数覆盖为解析消息,我需要使用终结器,或者可以使用SuppressFinalize ?,如果我需要使用终结器...我该怎么办?只是我不评论Finalize子项,仅此而已?我不确定终结器的用途或何时以及如何使用它。







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

  #Region处置 

'''< summary>
’’处置由此类创建的所有对象。
’’< / summary>
Public Sub Dispose()_
实现IDisposable.Dispose

'处理
p.Dispose()

'公共财产
Me.mp3val_location =否
Me.CheckFileExist =否

'字符串变量
StandardError =否
StandardOutput =否
信息=否
警告=没有
错误=没有
标签=没有

'RegEx变量
Info_RegEx =没有
Warning_RegEx =没有
Fixed_RegEx = Nothing

'EventArgs变量
StartedArgs =无
ExitedArgs =无

GC.SuppressFinalize(Me)

End Sub

#End Region




UPDATE


所以...简化了令人困惑的VS生成的代码,使其更加直观和实用关于我的要求,我应该这样使用吗?:

 公共类测试:实现IDisposable 

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

受保护的可覆盖子Dispose(IsDispose为布尔值) )

静态IsBusy为布尔型'检测冗余呼叫。

如果不是很忙并且也正在进行DisDispose然后

'在此处处理...
'myProcess.Dispose()

End If

IsBusy =真

结束子级

结束类


解决方案


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


无。你没有您应该做的是在 using 块中创建类的所有实例。这将在适当的时间自动调用 Dispose()。失败的话,请始终在 try 块的一部分中创建类,并在 Dispose()中调用它。 最终块。


如果我将那些值设为[b],会更好


不。不需要这个。字符串和整数变量仅使用内存,垃圾回收器 将正确处理这些变量,而无需进行任何额外的工作。


我的班级调用了一些WinAPI函数,并且还重写了WndProc子句以解析消息,我需要使用终结器,还是可以使用SuppressFinalize ?,如果我需要使用终结器... [我需要做什么] ?


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

 'IDisposable 
受保护的可重写子Dispose(以布尔值处理)
如果不是Me.disposedValue,则
如果处置,则
'TODO:处置托管状态(托管对象)。
End if

’TODO:释放非托管资源(非托管对象)并覆盖下面的Finalize()。
’TODO:将大字段设置为null。
End如果
Me.disposedValue = True
End Sub

这里的窍门是TODO注释令人困惑……甚至产生误导。第一个注释(处置托管状态)是完全没有价值的,因为您永远无法自行处置托管状态。这完全取决于垃圾收集器。考虑到这一点,如果条件完全可以删除。我发现此规则的唯一例外是事件处理程序。您可以使用此位置退订课程中的任何委托。



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



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


VS generates automatically these regionized procedures when I Implement IDisposable:

#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

Imagine that my class has one disposable object (a new Process from Process Class) that never is closed/disposed, so I want to dispose it implementing the IDisposable on the Class...

My questions are:

  • In what line EXACTLY of the code above I need to put a myProcess.Dispose()?

  • I have some String and Integer variables which are not disposable like for example dim myVar as string = "value", then is better if I turn the values of those vars to a null value when I dispose the disposable objects? something like this?:

    sub dispose()
      myProcess.Dispose()
      myvar = nothing
    end sub
    

  • My Class calls some WinAPI functions and also overrides the WndProc sub to parse messages, I need to use a finalizer or I could use the SuppressFinalize?, if I need to use the finalizer... what I need to do? just I uncomment the Finalize sub and that's all?. I'm not sure about the purpose of the Finalizer or when and how I need to use it.


While I don't know exactly the right way to implement the Dispose method, I'm disposing it in this way, but sure is totally wrong in one or other way...:

#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

UPDATE

So... simplifying the confussing VS generated code to do it more intuitive and friendly about my requeriments, I should use it like this?:

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

解决方案

In what line EXACTLY of the code above I need to put a myProcess.Dispose()

None. You don't. What you should do is create any instances of your class as part of a using block. This will call Dispose() at the appropriate time automatically. Failing that, always create your class as part of a try block and call Dispose() for it as part of the finally block.

Is [it] better if I turn the values of those vars to a null value when I dispose the disposable objects?

No. There is no need for this. String and int variables only use memory, and the garbage collector will take care of these correctly without any extra work.

My Class calls some WinAPI functions and also overrides the WndProc sub to parse messages, I need to use a finalizer or I could use the SuppressFinalize?, if I need to use the finalizer... what [do] I need to do?

You need a finalizer if your WinAPI calls allocate any system resources, such as file handles, gdi handles, threads, sockets, etc, and if this isn't as part of an existing .Net class that will handle releasing those resources for you. You only need a finalizer if both of those conditions are true. Very often, the finalizer will just call the .Dispose(False) method, as shown in the commented example, so that your cleanup code only needs live in one place.

Therefore, when implementing IDisposable, most of the time you only need to be concerned with the first method in that sample. You may also want to uncomment the Finalize() method, but that's it. Now let's look at that method:

' 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

The trick here is that the TODO comments are confusing... misleading, even. The first comment ("dispose managed state") is completely worthless, because you can never dispose managed state on your own. This is entirely up to the garbage collector. With that in mind, you can remove that if condition entirely. The only exception I've ever found to this rule is for event handlers. You can use this place to unsubscribe any delegates in your class.

The second TODO comment ("free unmanaged resources") is more useful. It tells you where to put the clean-up code for your unmanaged resource. It just goes on too long. If it stopped after the first phrase, it would be clearer. If your class itself wraps instances of any IDisposable classes, this is a good place to call .Dipose() for objects.

The third TODO comment ("set large fields to null") is also largely unnecessary. It usually doesn't help you at all setting items to NULL in .Net. In this case, you're already disposing the object. This means it's very probably about to go out of scope anyway, and those objects would still be eligible for collection the next time the GC runs. The only reason to do this is if you suspect your object will not go out of scope soon after it's disposed. In that case, setting those fields to null may allow those larger memory blocks to be collected sooner... but this situation would be a symptom of poor design by users of your class.

这篇关于实施IDisposable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆