1
votes

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
1
To start with, you should follow the comment that says Do not change this code.. Move everything except the GC.SuppressFinalize call to Dispose(disposing As Boolean) and revert Dispose() to its original form, then we can work from there.Sam Harwell
@280Z28 thanks for comment, but exactly where? the sub that you say has two IF statements, exactly where in that sub I need to move all?. I move all to inside of If Not Me.disposedValue Then... or inside If disposing Then..., or I should put all outside those If's?ElektroStudios
@280Z28 please see my update and comment if you could...ElektroStudios
Someone could tell me if I wrote the piece of code correctly in my last update please?ElektroStudios

1 Answers

1
votes

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.