Here are two classes that allocate resources, the first class needs to implement a destructor and Dispose, but the second class doesn’t need to. The difference is that the first class allocates resources in the constructor and doesn’t clean them up immediately. In contrast, the second class allocates resources in a member function and carefully frees them before exiting (using a finally block), so the second class author doesn’t need to bother writing Dispose and a destructor.
class MustDispose
{
public MustDispose()
{
  create a 3rd party object
  open a file handle
  allocate some memory
  open a database connection
  open a network port
}
~MustDispose()
{
  // customized destructor for this class
  if (3rd party object != null)free the 3rd party object
  if (file handle != null)close the file handle
  if (memory != null)free the memory
  if (connection != null) close the database connection
  if (port open) close the network port
}
public void Dispose()
{
  // because this class needs a destructor, it also needs this
  // idiomatic Dispose method
  Finalize();
  System.GC.SuppressFinalize(this);
}
};
class NoDispose
{
public NoDispose()
{
  // this class has an uninteresting constructor so it doesn't need
  // a destructor or Dispose
}
MemberFuncThatCleansUp()
{
try
{
  create a 3rd party object
  open a file handle
  allocate some memory
  open a database connection
  open a network port
}
finally
{
  if (3rd party object != null)free the 3rd party object
  if (file handle != null)close the file handle
  if (memory != null)free the memory
  if (connection != null) close the database connection
  if (port open) close the network port
}
}
}
If a class needs a destructor, you should customize how it is written. However, the Dispose method has become an idiom in C# for any class that needs a destructor:
public void Dispose()
{
  Finalize();
  System.GC.SuppressFinalize(this);
}
When to Call Dispose
Call Dispose on an object you create if the class author provides Dispose. Call Dispose as soon as you are done using an object, especially if the object will remain in scope during a lengthy operation or if the object allocates significant resources of its own. If the object you create doesn’t itself allocate significant resources (but how do you know that?) then it might not be a problem to simply let the object go out of scope and have C# call its destructor automatically.
Finally, here’s a C# tip to actually avoid calling dispose:
MustDispose obj = new MustDispose;
try
{
  // use the object
}
finally
{
  if (obj != null)
   ((IDisposable)obj).Dispose();
}
You can shorten this up and just write this instead:
using (MustDispose obj = new MustDispose)
{
  // use the object
}
This assumes that exceptions will be caught at a higher level, which is usually recommended. In other words, don’t catch just to throw.
Scott Zimmerman is an award-winning .NET developer.
scottz1@hotmail.com