Please Note: This question is about the difference in terminology between the words \"destructor\" and \"finalizer\" and their correct usage. I have merely provided
I believe 'destructor' is the C# code, and the 'finalizer' is the compiled CIL method. The C# compiler turns a destructor into a finalizer.
EDIT: To be more verbose; The C# language specification defines a 'destructor' as a C# instance method on a class. 'destructor', then, is part of the C# grammar -- destructors are a linguistic object appearing in source code.
A destructor is a member that implements the actions required to destruct an instance of a class. Destructors cannot have parameters, they cannot have accessibility modifiers, and they cannot be invoked explicitly. The destructor for an instance is invoked automatically during garbage collection.
A 'finalizer' is a term used in the Common Language Runtime, for example in calls to GC.WaitForPendingFinalizers()
, and it refers to any .net language, not just C#. Any .net reference type can have a finalizer. For a C# class (the source code artifact), the destructor compiles into the CIL method which is the CLR type's finalizer.
Or more succinctly, destructor is to finalizer as source code is to machine code ;)
Strictly speaking C# doesn't have a destructor (I believe the C# spec is confusing on this point).
C#'s finalizer looks like a C++ destructor but, as you say, is non-deterministic.
C# has deterministic clean-up in the form of IDisposable::Dispose
(but this is still not called a destructor).
C++/CLI has deterministic destructors, which look like C++ destructors. At the CLI level these map onto IDisposable::Dispose()
(IDisposable
is implemented for you ).
C++/CLI has non-deterministic finalizers, which look like destructors but use the ! prefix instead of the ^ prefix.
The fact that C++/CLI uses the same syntax for destructors that C# uses for finalizers can be a little confusing - but it fits better with C++, which has a strong tradition of deterministic destruction.
Unfortunately the lack of universal definitions of these terms means you always need to clarify what you are talking about. Personally I always use the word finalizer when talking about the C# concept and reserve destructor for contexts where it definitely implies deterministic destruction.
[Update] Since my original post here Eric Lippert has posted his response (the accepted answer) and followed up with a blog post on the same. I'm glad to see we're in agreement :-)
If we abide to the "deterministic" definition of destructors, then I would say that in .NET objects have no destructors unless explicitly implemented by using the IDisposable interface.
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.