The difference between a destructor and a finalizer?

1) Is there a well-defined difference between “destructor” and “finalizer” as used in industry or academia?

There certainly appears to be. The difference seems to be that destructors are cleanup methods that are invoked deterministically, whereas finalizers run when the garbage collector tells them to.

2) In that case, the C# spec gets it wrong — finalizers are called “destructors” in C#. Why did the authors of the C# spec get it wrong?

I don’t know, but I can guess. In fact, I have two guesses.

Guess #1 is that on May 12th, 1999 there was not a wikipedia article clearly describing the subtle difference between these two concepts. That’s because there wasn’t a wikipedia. Remember back when there wasn’t a wikipedia? Dark ages, man. The error might simply have been an honest mistake, believing that the two terms were identical.

Heck, for all I know, the two terms were identical on May 12th, 1999, and the difference in definitions only evolved later, as it became obvious that there was a need to disambiguate between eager and lazy cleanup methods.

Guess #2 is that on May 12th, 1999, the language design committee wished to leave open the possibility that a “destructor” could be implemented as something other than a finalizer. That is, the “destructor” was designed to be a C# language concept that did not necessarily map one-to-one with the .NET “finalizer” concept. When designing a language at the same time as the framework it sits atop is also being designed, sometimes you want to insulate yourself against late-breaking design changes in your subsystems.

The language committee’s notes for May 12th 1999 read in part:

We’re going to use the term
“destructor” for the member which executes
when an instance is reclaimed. Classes
can have destructors; structs can’t.
Unlike in C++, a destructor cannot be
called explicitly. Destruction is
non-deterministic – you can’t reliably
know when the destructor will execute,
except to say that it executes at some
point after all references to the
object have been released. The
destructors in an inheritance chain
are called in order, from most
descendant to least descendant. There
is no need (and no way) for the
derived class to explicitly call the
base destructor. The C# compiler
compiles destructors to the
appropriate CLR representation. For
this version that probably means an
instance finalizer that is
distinguished in metadata. CLR may
provide static finalizers in the
future; we do not see any barrier to
C# using static finalizers.

So, there, you now know everything I know on the subject. If you want to know more, ask Anders next time you see him.

Leave a Comment