views:

63

answers:

2

I'm really looking for some best practice wisdom. So here are the questions, I'll add more if people leave comments. Feel free to answer some or all of these questions.

When SHOULD I use IDisposable? Only when I have unmanaged resources?

What variations of the dispose pattern are there and why do they vary?

What are common unmanaged resources I should be aware of?

Is it ever wrong or misleading to implement IDisposable?

Should Dispose calls ever be chained together, or should we rely on using statements? For instance:

public Dispose(bool disposing)
{
  ...
  this.SomeDependency.Dispose;
}
+3  A: 

Wow. A lot of questions here!

When SHOULD I use IDisposable? Only when I have unmanaged resources?

IDisposable is usually used to clean up resources, but that's not necessarily all it's good for. It's a general pattern to notify the object being consumed that you're done with it. One example is a timer:

using(var timer = new MyTimer())
{
    //do some stuff
}

In this case, calling Dispose isn't necessarily releasing any resources, it's just a convenient & consistent (two keys for a pattern!) way to tell the timer "OK, I'm done with you now" and the timer can stop timing, and maybe record the time somewhere.

Another good rule of thumb is if you need to have a finalizer, for whatever reason, you should usually also provide IDisposable access to the same routine so the consuming class can opt to finalize the class earlier instead of waiting on the GC.

What variations of the dispose pattern are there and why do they vary?

There is only one real "specific" type of IDisposable implementation I'm aware of - the Finalize/Dispose pattern:

public class MyClass : IDisposable
{
   void IDisposable.Dispose() 
   {
     Dispose(true);
     GC.SuppressFinalize(this); 
   }

   protected virtual void Dispose(bool disposing) 
   {
      if (disposing) 
      {
         // Free other state (managed objects).
      }
      // Free your own state (unmanaged objects).
      // Set large fields to null.
   }

   ~MyClass()
   {
      Dispose(false);
   }
}

What are common unmanaged resources I should be aware of?

Anything that implements IDisposable, especially in the .NET libraries, should be assumed to have handles to unmanaged resources and should be disposed. Typically you'll only access unmanaged resources through these. If not, you'll know - usually building a driver or something.

Is it ever wrong or misleading to implement IDisposable?

It can be pointless to overuse it, but not directly harmful.

Should Dispose calls ever be chained together

A class should only dispose any IDisposables that it creates internally. If it has disposable dependencies that were injected or live beyond the scope of the class, you should never dispose them.

Rex M
Great answers! well thought out sir!
Firoso
A: 

There are two primary things I've written regarding IDisposable, and I recommend you read at least the first one: How to Implement IDisposable and Finalizers - 3 Easy Rules (I also have other blog posts on the subject) and IDisposable - What Your Mother Never Told You about Resource Deallocation.

When SHOULD I use IDisposable? Only when I have unmanaged resources?

IDisposable should be used for one of three things: freeing an unmanaged resource, freeing managed resources, and RAII. I prefer to use different patterns for these different needs.

Note that the rest of my answers (and the links) are all discussing IDisposable in the context of freeing resources. They don't address RAII.

What variations of the dispose pattern are there and why do they vary?

The Microsoft pattern is the most well-known. It handles freeing unmanaged and managed resources and allowing for inheritance. I prefer a simpler pattern described on my blog (3 easy rules), which is the pattern that Microsoft has actually followed since .NET 2.0.

What are common unmanaged resources I should be aware of?

My preference is to have a single IDisposable class for each type of unmanaged resource (akin to Microsoft's SafeFileHandle). So, any time you add a type of unmanaged resource to your program/library, you only have to handle it once.

The question then becomes "which classes should I dispose?", which has a simple answer: "all classes that implement IDisposable."

Is it ever wrong or misleading to implement IDisposable?

No. An empty IDisposable implementation is always an option. You should consider adding IDisposable to interfaces or base classes if you think an implementation may use them. This is a design issue, which I discuss more in my What Your Mother Never Told You article.

Should Dispose calls ever be chained together, or should we rely on using statements?

It's common for Dispose to call Dispose on all member objects that it owns. See my second rule blog post for more details.

Stephen Cleary
Unexplained dv??
Stephen Cleary