Free mag vol1 | Page 553

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