The unique thing about the IDisposable interface is that the language actually provides a specific construct for it: the "using" block:
public void SomeMethod()
{
using(IDisposable myDisposable = new SomeClassThatImplementsIDisposable())
{
//Do something with your disposable...
}
//And, it's out of scope here
}
This is a bit of syntactic sugar where what's actually going on is this:
public void SomeMethod()
{
IDisposable myDisposable = new SomeClassThatImplementsIDisposable();
try
{
//Do something with your disposable...
}
finally
{
myDisposble.Dispose();
}
//And, it's out of scope here
}
So, when you implement IDisposable, you're giving clients of your class a way to use it where they can ensure (for the most part) that the cleanup you intend for your class actually happens.
This is most common and critical in classes that hold unmanaged resources. For instance, if your class were holding a database connection, you wouldn't want clients to let it go out of scope without ever closing the connection, as that would be a memory leak. The IDisposable usage above also ensures that if some exception is generated, the "finally" implied by the "using()" will invoke your dispose so that you can at least clean up.
That said, there are certainly situations where you might use it for managed resources. One example that comes to mind off the top is if an instance of your class is listening to events raised by an instance of a longer lived class than yours. Without disposal, this also creates a memory leak (a common problem in .NET).
So, generally speaking, I'd use it in circumstances where it would be bad if an instance of your class went out of scope without all cleanup code being executed. Implementing IDisposable advertises to any clients of your class that there are resources that it holds that need to be disposed of properly.