An object should implement IDisposable
if it will know of things that need to happen sometime before the end of the universe, and nothing else is going have the knowledge and impetus necessary to ensure that those things get done; the Dispose
method lets the object know that it had better do those things immediately, because otherwise they'll likely never get done.
An abstract type or interface should implement IDisposable
if it is likely that instances of a derived or implementing that type might know of things that need to happen sometime before the end of the universe, and the last entity holding a reference is apt to know that it's an instance of something derived from or implementing the abstract or interface type, rather than as something which implements a more specific type that implements IDisposable
.
A type which implements an interface that inherits IDisposable
will be required to implement IDisposable
, whether or not it would have any other reason for doing so.
Types which have reason to implement IDisposable
should do so. Types which don't, shouldn't.
ADDENDUM
To understand why one shouldn't always implement IDisposable
, it may be helpful to consider the real cost of doing so. The amount of time required for the processor to call a do-nothing Dispose
method is trivial, but that isn't the real consideration. The bigger issue comes when one considers that most objects fit one of four descriptions:
Objects which encapsulate resources, and need to have one clearly-defined owner
Objects which encapsulate mutable state, and need to have one clearly-defined owner.
Objects of immutable types, which do not need to have clearly-defined owners.
Instances of mutable types which will never be exposed to code that could mutate them, and do not need to have clearly-defined owners.
Correct use of mutable objects generally requires keeping track of who owns them, as is the case with objects that hold resources. Likewise, if an object with mutable state is used to encapsulate mutable state for another object, proper use of the latter object will require keeping track of who owns it, as is the case with objects encapsulating other objects that own resources. The difference is between objects with resources and those with mutable state is that when an instance of a mutable type is used to encapsulate the state of an immutable object (ensuring the instance is never exposed to code that would mutate it), it will no longer be necessary to keep track of who owns it. By contrast, it's necessary to track ownership of objects which encapsulate other objects that hold resources, even if those objects are semantically immutable.