CHAPTER 13 UNDERSTANDING OBJECT LIFETIME
Note It is illegal to override Finalize() on structure types. This makes perfect sense given that structures
are value types, which are never allocated on the heap to begin with and, therefore, are not garbage collected!
However, if you create a structure that contains unmanaged resources that need to be cleaned up, you can
implement the IDisposable interface (described shortly).
Of course, a call to Finalize() will (eventually) occur during a “natural” garbage collection or
possibly when you programmatically force a collection via GC.Collect(). In addition, a type’s finalizer
method will automatically be called when the application domain hosting your application is unloaded
from memory. Depending on your background in .NET, you may know that application domains (or
simply AppDomains) are used to host an executable assembly and any necessary external code libraries.
If you are not familiar with this .NET concept, you will be by the time you’ve finished Chapter 17. For
now, note that when your AppDomain is unloaded from memory, the CLR automatically invokes
finalizers for every finalizable object created during its lifetime.
Now, despite what your developer instincts may tell you, the vast majority of your C# classes will not
require any explicit cleanup logic or a custom finalizer. The reason is simple: if your classes are just
making use of other managed objects, everything will eventually be garbage-collected. The only time
you would need to design a class that can clean up after itself is when you are using unmanaged
resources (such as raw OS file handles, raw unmanaged database connections, chunks of unmanaged
memory, or other unmanaged resources). Under the .NET platform, unmanaged resources are obtained
by directly calling into the API of the operating system using Platform Invocation Services (PInvoke) or
as a result of some very elaborate COM interoperability scenarios. Given this, consider the next rule of
garbage collection:
Rule The only compelling reason to override Finalize() is if your C# class is making use of unmanaged
resources via PInvoke or complex COM interoperability tasks (typically via various members defined by the
System.Runtime.InteropServices.Marshal type). The reason is that under these scenarios, you are
manipulating memory that the CLR cannot manage.
Overriding System.Object.Finalize()
In the rare case that you do build a C# class that uses unmanaged resources, you will obviously want to
ensure that the underlying memory is released in a predictable manner. Suppose you have created a new
C# Console Application named SimpleFinalize and inserted a class named MyResourceWrapper that uses
an unmanaged resource (whatever that might be) and you want to override Finalize(). The odd thing
about doing so in C# is that you can’t do it using the expected override keyword.
class MyResourceWrapper
{
// Compile-time error!
protected override void Finalize(){ }
}
486