Sunday, August 07, 2005

Finalizer and Disposer

Finalizer is an implict cleanup, which relies on the GC to clean up the resources, while the disposer is explicit cleanup, which allows to clean up the resources explictly. The .Net supports both patterns, so it is very important to distinguish them. In general, explicit cleanup should be used favorably over the implict cleanup, since the resources are generally more precious than memory, we shouldn't really rely on the GC to hold it for long time and clean it after an unspecified time.

Annotation (Brian Grunkemeyer): There are two different concepts that are somewhat intertwined around object tear-down. The first is the end of the lifetime of a resource (such as a Win32 file handle), and the second is the end of the lifetime of the object holding the resource (such as an instance of FileStream). Unmanaged C++ provided destructors which ran deterministically when an object left scope, or when the programmer called delete on a pointer to an object. This would end the resource’s lifetime, and at least in the case of delete, end the lifetime of the object holding onto the resource. The CLR’s finalization support only allows you to run code at the end of the lifetime of the object holding a resource. Relying on finalization as the sole mechanism for cleaning up resources extends the resource’s lifetime to be equal to the lifetime of the object holding the resource, which can lead to problems if you need exclusive access to that resource or there are a finite number of them, and can hurt performance. Hence, witness the Dispose pattern for managed code, allowing you to define a method to explicitly mimic the determinism & eagerness of destructors in C++. This relegates finalization to a backstop against users of a type who do not call Dispose, which is a good thing considering the additional restrictions on finalizers.

In the Dispose(bool disposing) method, if the diposing passed in is true, it means that we can explicitely use other reference types that refer to other objects knowing for sure that those other objects have not been finalized or disposed yet. If it's false, we cannot refer to other resources since those objects may have already been freed.

When we inherit a class which has already correctly implemented "IDispose" pattern, we need only override the Dispose (bool disposing) class, we don't need to override the Finalize and Dipose class.

No comments: