There’s a bit more to implementing the
IDisposable interface than just one
Dispose method. For non-deterministic finalization to work properly you need to implement the disposable pattern shown below, making sure to distinguish between whether cleanup is being done via the public
Dispose method, or via the finalizer (destructor) during garbage collection.
Dispose method actually does all of the work while the
_disposed field ensures cleanup only happens once. The
disposeManaged parameter indicates whether disposal is being triggered by a call to the public
Dispose method by some client code (for example, when the object goes out of scope of a using statement) or if the finalizer has been called by the .NET runtime garbage collector. If the public
Dispose method is called, then finalization is prevented by a call to the static method
GC.SuppressFinalize. Again, this is to prevent cleanup happening twice.
One really important point to note is that any derived classes must not implement their own finalizers.
Making it reusable
Just like with the
IEquatable<T> interface, this has suddenly added a lot of noise to our class which doesn’t even do anything yet, decreasing readability and maintainability. Time for a reusable base class.
Now all you need to do in a derived class is implement the
DisposeUnmanaged methods (and avoid adding a finalizer).
DisposeUnmanaged are called automatically so do not call them directly. However if there is more than one level of inheritance, remember to call the base implementations of
DisposeUnmanaged like so: