Results 1 to 5 of 5

Thread: When to use IDisposable?

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2001
    Posts
    1,331

    When to use IDisposable?

    Hello,

    I have been working on this for a while now. And I am still confused about some issues. My questions below

    1) I know that you only need a finalizer if you are disposing of unmanaged resources. However, if you are using managed resources that make calls to unmanaged resources. Would you still need to implement a finalizer?

    2) However, if you develop a class that doesn't use any unmanged resources directly or indirectly and you implement the IDisposable so that clients of your class can use the 'using statement'. Would it be acceptable to implement the IDisposable just so that clients of your class can use the using statement?
    Code:
    myClass objClass = new myClass()
    using objClass
         'Do work here
    End Using
    3) I have developed this simple code below to demostrate the Finalize/dispose pattern:
    Code:
    Public Class NoGateway
    	Implements IDisposable
    		Private wc As WebClient = Nothing
    
    		Public Sub New()
    			 wc = New WebClient()
    			 Using wc
    				AddHandler wc.DownloadStringCompleted, AddressOf wc_DownloadStringCompleted
    		     End Using
    		End Sub
    
    		
    		' Start the Async call to find if NoGateway is true or false
    		Public Sub NoGatewayStatus()
    		   ' Start the Async's download
    		   wc.DownloadStringAsync(New Uri(www.xxxx.xxx))
    		   ' Do other work here
    		End Sub
    
    		Private Sub wc_DownloadStringCompleted(ByVal sender As Object, ByVal e As DownloadStringCompletedEventArgs)
    		   ' Do work here
    		End Sub
    
    		' Dispose of the NoGateway object
    		Public Sub Dispose()
    			RemoveHandler wc.DownloadStringCompleted, AddressOf wc_DownloadStringCompleted
    			wc.Dispose()
    			GC.SuppressFinalize(Me)
    		End Sub
    End Class
    Question about the source code:
    1) Here I have not added the finalizer. And normally the finalizer will be called by the GC, and the finalizer will call the Dispose. As I don't have the finalizer, when do I call the Dispose method? Is it the client of the class that has to call it?

    2) I have added my RemoveHandler in the Dispose method. Is this the place I should be removing it?

    3) I am using the 'using statement' to create the webclient. However, is this bad design as when the code executes at the end of the 'using statement' the webclient object will no longer exist?

    4) I am using the webclient class in my 'NoGateway' class. Because the webclient implements the IDisposable interface. Does this mean that the webclient indirectly uses unmanaged resources? Is there any hard and fast rule to follow about this. How do I know that a class uses unmanaged resources?

    5) Is my source correctly implementing the Finalize/Dispose pattern if the webclient is using unmanaged resources.

    Sorry for the long list of questions here. However, just trying to get this 100% clear to me.

    Many thanks,
    steve

  2. #2
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: When to use IDisposable?

    Your dispose sub includes you disposing wc, but you already disposed it in your using statement in the New sub.

    Edit: Now I see your question #3. Yes, that object will be disposed after it adds that handler.
    Last edited by ForumAccount; May 21st, 2009 at 10:36 PM.

  3. #3
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: When to use IDisposable?

    In truth, there really are only unmanaged resources. A managed resource is just a managed object that itself holds unmanaged resources, or holds a reference to another managed resource. If you have a managed object that has a reference to a managed object that has a reference to a managed object that holds an unmanaged resource then there's really only one resource, but all the managed objects are considered managed resources. Any and every managed resource must have a Dispose method. If a class has a Dispose method then it's a managed resource. If a class holds managed or unmanaged resources then it MUST have a Dispose method.

    So, it's going to be relatively rare that your managed objects hold unmaanged resources directly, although it will happen sometimes. More likely is that you will have a reference to a managed resource, which is an indirect reference to an unmanaged resource.

    Implementing the IDisposable interface is easy. You simply type "implements idisposable" under your class declaration and hit Enter:
    vb.net Code:
    1. Public Class NoGateway
    2.     Implements IDisposable
    3.  
    4.     Private disposedValue As Boolean = False        ' To detect redundant calls
    5.  
    6.     ' IDisposable
    7.     Protected Overridable Sub Dispose(ByVal disposing As Boolean)
    8.         If Not Me.disposedValue Then
    9.             If disposing Then
    10.                 ' TODO: free other state (managed objects).
    11.             End If
    12.  
    13.             ' TODO: free your own state (unmanaged objects).
    14.             ' TODO: set large fields to null.
    15.         End If
    16.         Me.disposedValue = True
    17.     End Sub
    18.  
    19. #Region " IDisposable Support "
    20.     ' This code added by Visual Basic to correctly implement the disposable pattern.
    21.     Public Sub Dispose() Implements IDisposable.Dispose
    22.         ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
    23.         Dispose(True)
    24.         GC.SuppressFinalize(Me)
    25.     End Sub
    26. #End Region
    27.  
    28. End Class
    You then simply replace the three TODOs with the appropriate code. If you have no managed resources then you can remove the first TODO, and therefore the If block too. If you have no unamanged resources you can remove the second TODO. If you have no large fields then you can remove the third TODO.

    In your case you would replace the first TODO with your RemoveHandler and webClient.Dispose code. The second TODO would go and you could set your WebClient field to Nothing in place of the third if you wanted.

    You are incorrectly using the Using statement in that code. The point of the Using block is to create an object that will be used only within that block and disposed at the End Using statement. Obviously that's not what you want.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Dec 2001
    Posts
    1,331

    Re: When to use IDisposable?

    Hello,

    Sorry to be a pain, just a few questions about your comments.

    I have made the adjustments to my code. I know VB does this, but I would like to do it myself, for my own understanding.

    vb Code:
    1. Public Class NoGateway
    2.     Implements IDisposable
    3.         Private wc As WebClient = Nothing
    4.  
    5.         Public Sub New()
    6.              wc = New WebClient()  
    7.              AddHandler wc.DownloadStringCompleted, AddressOf wc_DownloadStringCompleted
    8.         End Sub
    9.    
    10.         ' Start the Async call to find if NoGateway is true or false
    11.         Public Sub NoGatewayStatus()
    12.            ' Start the Async's download
    13.            wc.DownloadStringAsync(New Uri([url]www.xxxx.xxx[/url]))
    14.            ' Do other work here
    15.         End Sub
    16.  
    17.         Private Sub wc_DownloadStringCompleted(ByVal sender As Object, ByVal e As DownloadStringCompletedEventArgs)
    18.            ' Do work here
    19.         End Sub
    20.  
    21.         ' Dispose of the NoGateway object
    22.         Public Sub Dispose()
    23.             RemoveHandler wc.DownloadStringCompleted, AddressOf wc_DownloadStringCompleted
    24.             wc.Dispose()
    25.             wc = Nothing
    26.         End Sub
    27. End Class

    As I am not using any unmanaged resources I have removed the if statement and the boolean, and also the GC.SuppreseFinalizer() as I don't have a finalizer that the GC will call.

    So when the client of this class it using it I could do 2 things that will call the Dispose()
    1)

    objNoGateway = new NoGateway()
    Using objNoGateway
    ' Use the object and when it reaches the end of the using statement it will automatically call the Dispose method
    End Using

    2) Manually dispose of the object

    objNoGateway = new NoGateway()
    ' use the object and when finished call the dispose method
    objNoGateway.Dispose()


    As my NoGateway wraps the WebClient class. I don't need to dispose of my NoGateway class as that is handled by the framework?

    Many thanks,
    steve

  5. #5
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: When to use IDisposable?

    You should absolutely NOT write out all the code yourself because you're actually making it harder to understand. Have you tried to compile that code? It will refuse and it will tell you that your class has no implementation for the IDisposable.Dispose method. That's because you have failed to add the Implements clause to your Dispose method, which the IDE would have done for you.

    Your code could also cause run time errors that would be hard to diagnose. Take a look at the code that the IDE generates. Notice that there are two Dispose methods? It does that for a reason. You say:
    As I am not using any unmanaged resources I have removed the if statement and the boolean
    but that is the exact opposite of what you should be doing. The If statement and the Boolean filed exist SPECIFICALLY for managed resources. If you go back and read my post again I said:
    If you have no managed resources then you can remove the first TODO, and therefore the If block too.
    This is all done for a reason and it's explained in the documentation but here goes anyway. If an instance of your class is created and assigned to a variable and then that variable loses scope before the object is disposed, it's going to be left up to the GC to dispose your object when it finalises it. At that point your Dispose method will be called and it will try to dispose the WebClient. Who's to say that the GC hasn't already cleaned up that WebClient object though? If it has then you'll get an exception thrown for trying to access invalid memory. That's why you MUST NEVER release managed resources unless the object is being explicitly disposed, which is why you need two Dispose methods.

    Just let the IDE implement the IDisposable interface for you and then follow the instructions it provides in the generated code. If you do that you know that it's done properly.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width