CHAPTER 13 UNDERSTANDING OBJECT LIFETIME
call instance void [mscorlib]System.Object::Finalize()
IL_0019: nop
IL_001a: endfinally
} // end handler
IL_001b: nop
IL_001c: ret
} // end of method MyResourceWrapper::Finalize
If you then tested the MyResourceWrapper type, you would find that a system beep occurs when the
application terminates, given that the CLR will automatically invoke finalizers upon AppDomain
shutdown.
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Finalizers *****\n");
Console.WriteLine("Hit the return key to shut down this app");
Console.WriteLine("and force the GC to invoke Finalize()");
Console.WriteLine("for finalizable objects created in this AppDomain.");
Console.ReadLine();
MyResourceWrapper rw = new MyResourceWrapper();
}
Source Code The SimpleFinalize project is included under the Chapter 13 subdirectory.
Detailing the Finalization Process
Not to beat a dead horse, but always remember that the role of the Finalize() method is to ensure that a
.NET object can clean up unmanaged resources when it is garbage-collected. Thus, if you are building a
class that does not make use of unmanaged memory (by far the most common case), finalization is of
little use. In fact, if at all possible, you should design your types to avoid supporting a Finalize() method
for the very simple reason that finalization takes time.
When you allocate an object onto the managed heap, the runtime automatically determines
whether your object supports a custom Finalize() method. If so, the object is marked as finalizable, and
a pointer to this object is stored on an internal queue named the finalization queue. The finalization
queue is a table maintained by the garbage collector that points to each and every object that must be
finalized before it is removed from the heap.
When the garbage collector determines it is time to free an object from memory, it examines each
entry on the finalization queue and copies the object off the heap to yet another managed structure
termed the finalization reachable table (often abbreviated as freachable, and pronounced “effreachable”). At this point, a separate thread is spawned to invoke the Finalize() method for each object
on the freachable table at the next garbage collection. Given this, it will take, at the very least, two garbage
collections to truly finalize an object.
The bottom line is that while finalization of an object does ensure an object can clean up
unmanaged resources, it is still nondeterministic in nature, and due to the extra behind-the-curtains
processing, considerably slower.
488