CHAPTER 13 UNDERSTANDING OBJECT LIFETIME
Next, you’d like to make sure that the Finalize() method does not attempt to dispose of any
managed objects, while the Dispose() method should do so. Finally, you’d also like to be certain the
object user can safely call Dispose() multiple times without error. Currently, our Dispose() method has
no such safeguards.
To address these design issues, Microsoft defined a formal, prim-and-proper disposal pattern that
strikes a balance between robustness, maintainability, and performance. Here is the final (and
annotated) version of MyResourceWrapper, which makes use of this official pattern:
class MyResourceWrapper : IDisposable
{
// Used to determine if Dispose()
// has already been called.
private bool disposed = false;
public void Dispose()
{
// Call our helper method.
// Specifying "true" signifies that
// the object user triggered the cleanup.
CleanUp(true);
}
// Now suppress finalization.
GC.SuppressFinalize(this);
private void CleanUp(bool disposing)
{
// Be sure we have not already been disposed!
if (!this.disposed)
{
// If disposing equals true, dispose all
// managed resources.
if (disposing)
{
// Dispose managed resources.
}
// Clean up unmanaged resources here.
}
disposed = true;
}
~MyResourceWrapper()
{
// Call our helper method.
// Specifying "false" signifies that
// the GC triggered the cleanup.
CleanUp(false);
}
}
Notice that MyResourceWrapper now defines a private helper method named CleanUp(). By specifying
true as an argument, we indicate that the object user has initiated the cleanup, so we should clean up all
494