Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The difference between a destructor and a finalizer?

Please Note: This question is about the difference in terminology between the words "destructor" and "finalizer" and their correct usage. I have merely provided examples of their use in C# and C++/CLI to demonstrate why I am asking the question. I am well aware of how it is implemented in both C# and the CLR, but I am asking about the correct use of terminology.


In the C# world the terms "destructor" and "finalizer" seem to be used pretty much interchangeably, which I suspect is because the C# specification describes the non-deterministic cleanup functionality using the word "destructor", whereas the CLR documentation always uses the word "finalizer", so within the realms of C# they mean the same thing.

However, in the C++/CLI specification there is a distinction made between the two. It allows both deterministic and non-deterministic cleanup, and uses the term "destructor" for the deterministic functionality and "finalizer" for the non-deterministic functionality:

The finalizer provides non-deterministic cleanup. A finalizer is a "last-chance" function that is executed during garbage collection, typically on an object whose destructor was not executed.

Additionally the Wikipedia descriptions of destructor and finalizer indicate that destructors and finalizers are separate concepts, and supports the C++/CLI spec's use of the terms with regard to determinism:

Unlike destructors, finalizers are not deterministic. A destructor is run when the program explicitly frees an object. A finalizer, by contrast, is executed when the internal garbage collection system frees the object.

The questions:

  • Is there, from a computer science point of view, a clearly defined difference between a "destructor" and a "finalizer", or is the terminology something that can only be defined contextually?

  • If there is a clearly defined difference, then why would the C# spec use the 'wrong' terminology?

like image 485
Greg Beech Avatar asked Dec 09 '09 09:12

Greg Beech


People also ask

What is the function of a finalizer and destructor?

Finalizers (historically referred to as destructors) are used to perform any necessary final clean-up when a class instance is being collected by the garbage collector. In most cases, you can avoid writing a finalizer by using the System.

Are finalizer finally block and destructor same?

Destructor implicitly calls the Finalize method, they are technically the same.

What is the finalizer?

A finalizer is called when an object is garbage collected – after an object has become garbage (unreachable), but before its memory is deallocated. Finalization occurs non-deterministically, at the discretion of the garbage collector, and might never occur.

What is a finalizer in C++?

Finalize is similar to traditional C++ destructors, as each is responsible for freeing object resources. C++ destructors are executed immediately when an object goes out of scope, whereas finalize is called during object cleanup at GC. In C#, finalize cannot be directly called or overridden.


2 Answers

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.

like image 172
Eric Lippert Avatar answered Oct 04 '22 01:10

Eric Lippert


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 :-)

like image 37
philsquared Avatar answered Oct 03 '22 23:10

philsquared