Free mag vol1 | Page 548

CHAPTER 13  UNDERSTANDING OBJECT LIFETIME Building Disposable Objects As you have seen, finalizers can be used to release unmanaged resources when the garbage collector kicks in. However, given that many unmanaged objects are “precious items” (such as raw database or file handles), it could be valuable to release them as soon as possible instead of relying on a garbage collection to occur. As an alternative to overriding Finalize(), your class could implement the IDisposable interface, which defines a single method named Dispose() as follows: public interface IDisposable { void Dispose(); } When you do implement the IDisposable interface, the assumption is that when the object user is finished using the object, the object user manually calls Dispose() before allowing the object reference to drop out of scope. In this way, an object can perform any necessary cleanup of unmanaged resources without incurring the hit of being placed on the finalization queue and without waiting for the garbage collector to trigger the class’s finalization logic.  Note Structures and class types can both implement IDisposable (unlike overriding Finalize(), which is reserved for class types), as the object user (not the garbage collector) invokes the Dispose() method. To illustrate the use of this interface, create a new C# Console Application named SimpleDispose. Here is an updated MyResourceWrapper class that now implements IDisposable, rather than overriding System.Object.Finalize(): // Implementing IDisposable. class MyResourceWrapper : IDisposable { // The object user should call this method // when they finish with the object. public void Dispose() { // Clean up unmanaged resources... // Dispose other contained disposable objects... } } // Just for a test. Console.WriteLine("***** In Dispose! *****"); Notice that a Dispose() method is not only responsible for releasing the type’s unmanaged resources, but can also call Dispose() on any other contained disposable methods. Unlike with Finalize(), it is perfectly safe to communicate with other managed objects within a Dispose() method. The reason is simple: the garbage collector has no clue about the IDisposable interface and will never call Dispose(). Therefore, when the object user calls this method, the object is still living a productive life 489