views:

447

answers:

6

This is something that I have never fully grasped in .NET as to the correct application of the .dispose() method.

Say I have something like

Public Class someClass()
  sub someMethod
    ' do some stuff tying up resources
  end sub
End Class

public class mainApp 
  dim _class as new SomeClass
  _class.someMethod()
End Class

In all cases is it good practice to implement a dispose method, and if so what should go in there?

If it is not the case that every class should have dispose method (which my gut feeling says the shouldn't) what classes should? I have always thought anything which may tie up a resource (i.e. connection, datareader etc) should have a .dispose() which would unallocate these resources.

Also how would you enforce a calling into calling the .dispose() method?

A: 

The Dispose() method is used for cleaning up any resources early. Although the garbage collector reclaims any unused memory for you, it's up to you to do deal with things like network/database connections and file handles. Normally, you'd want these things freed up as soon as they're no longer needed, so you implement the disposable pattern and take advantage of the Using statment for calling it within a try/finally block behind the scenes.

Mark Cidade
+5  A: 

I highly recommend reading Cleaning Up Unmanaged Resources on MSDN, it has articles touching on when to use Dispose and how to implement IDisposable correctly. Your gut instinct is mostly correct as you rarely have to implement IDisposable, unless your class uses unmanaged resources or is a container for an object that implements IDisposable.

As to enforcing the calling of Dispose, when you properly implement the IDisposable interface you attach a finalizer which calls Dispose to catch those stragglers and deviant classes that forgot.

Relevant articles:

Implementing a Dispose Method

Describes the implementation of the Dispose method for releasing unmanaged resources.

Using Objects That Encapsulate Resources

Describes ways to ensure that the Dispose method is called, such as the C# using statement (Using in Visual Basic).

(edit: additional information added)

In your example you have SomeClass.SomeMethod which does some work, presumably with a resource. If this resource isn't a class member, you may be better served wrapping it in a using-statement, and forgetting about the devilish details of IDisposable.

Public Class someClass()
  sub someMethod
    Using someResource As New ResourceType( arguments )
       ' no worries about IDisposable for someResource, as it is automatic
    End Using
  end sub
End Class
sixlettervariables
I would also highly recommend an article titled "IDisposable: What Your Mother Never Told You About Resource Deallocation" at http://www.codeproject.com/KB/dotnet/IDisposable.aspx - although it might make you feel that using IDisposable in an absolutely correct way is nearly hopeless.
romkyns
A: 

In general, you should you implement IDisposable whenever your class intends to OPEN something. Whether its a handle to a file, a connection to a database, or some resource which will take up a sizable chunk of memory or which will leave your application in an unstable state, it's always a good idea implement IDisposable to specify the code that will CLOSE those resources.

You really can't enforce other developers to call your dispose methods, but implementing IDisposable automatically means we can use the Using statement; which, once you get into the habit, is hard to break :)

Jeremy Frey
+6  A: 

It's a fairly long answer to cover everything fully, so hopefully nobody will mind if I link to a blog post which should hopefully answer everything.

Greg Beech
@Greg Beech: +1, great blog post.
sixlettervariables
+1  A: 

There is a lot of misinformation out there about IDisposable. It is a PATTERN that helps to accomplish what used to be traditionally accomplished via a destructor in C++. The problem is that in .NET, destruction of an object is not deterministic (it doesn't happen automatically when an object goes out of scope, but rather occurs at the time of Garbage Collection which is on a seperate low priority thread).

You do not need to implement Dispose unless you have a resource which needs to be released in some fashion. For instance, if any of your private data members implement Dispose, you should probably implement Dispose as well and call Dispose on those private members in your Dispose. Likewise, you should release any PInvoke handles in Dispose.

Also, the Dispose method is NOT called automatically for you upon garbage collection. This is the biggest piece of misinformation. You have to call Dispose from your Destructor (C#) or Finalize (VB.NET). Here is a good pattern for implementing Dispose:

public class Foo : IDisposable
{
   public Foo()
   {
      // Allocate some resource here
   }

   ~Foo()
   {
      Dispose( false );
   }

   public void Dispose()
   {
      Dispose( true );
   }

   private void Dispose( bool disposing )
   {
      // De-allocate resource here
      if ( disposing )
         GC.SuppressFinalize( this );
   }
}

The reason that you call GC.SupressFinalize is that if your object has a finalizer, your object will actually get promoted to the next GC generation, because it has to call Finalize the first time the GC runs around, and can't release your object until finalization is finished, and therefore the memory is actually not released until the 2nd run through by the GC. If you call Dispose manually, then you can skip the finalizer, allowing your object to be released during the first pass of the GC.

To get the most benefit out of Dispose, use the using keword:

using ( Foo f = new Foo() )
{
   // Do something with Foo
}

This is exactly the same as if you had written this:

Foo f;
try
{
   f = new Foo();
   // Do something with Foo
}
finally
{
   f.Dispose();
}

Some people like to set a boolean in their class called _disposed, and then check that bool during every method call, and throw an exception if you attempt to call a method on an object after Dispose is called. For internal project classes, I generally consider this overkill, but might be a good thing to do if you are creating a library for consumption by 3rd parties.

Nick
Usually if I am disposing something, I set it to null immediately afterwards. That way the finalizer can check that it's null instead of having to have an extra special boolean flag
Orion Edwards
Hm, it seems everything you said is against the Microsoft recommended design-pattern for the IDisposable Implementation. Therefore, using your advice would conflict with how Microsoft uses and calls Dispose, Dispose(disposing), and Finalize. -1
AMissico
@AMissico? How so? It looks like they track pretty closely to each other. I may not have copy and pasted Microsoft code, the pattern is the same.
Nick
See "Implementing Finalize and Dispose to Clean Up Unmanaged Resources" at <http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx>.
AMissico
You state, "You have to call Dispose from your Destructor (C#) or Finalize (VB.NET)." Absolutely not. You call Dispose(False).
AMissico
You state, "the Dispose method is NOT called automatically for you upon garbage collection." Correct. The Dispose method allows the user to "destroy" the object (release resources) when needed. The system uses Finalize. The user uses Dispose. The Dispose(boolean) is just helper method.
AMissico
You state, "Some people like to set a boolean in their class called _disposed." Well, you kind need this flag to avoid generating errors when disposing resources multiple times.
AMissico
Throwing the ObjectDisposedException is not part of the design pattern Microsoft recommends.
AMissico
A: 

You should implement IDisposable in a class if the class either:

  • own some other objects which implement IDisposable
  • allocates some ressources through an unmanaged interface like P/Invoke.
JacquesB