Why destructors and not just Finalize()?

In one of the comments, Niall said:

“I am curious as to why the C# syntax for a finalizer is the destructor syntax. It doesn't bother me one way or another, but I am still curious.”

So I thought I'd devote a bit of time to that question.

Say I'm writing some code that wraps some sort of resource. Here's the code I might write if C# didn't support the destructor syntax (and the class already has implemented the Dispose design pattern:

class MyClass: MyBaseClass
    IntPtr myResource;
    ... lots of stuff here...

    protected override void Finalize()

     protected override void Dispose(bool disposing)
        // free myResource here...

That seems pretty straightforward. What's wrong with the code?

The answer is the reason that we have a separate syntax. Please post your answer in the comments.

Comments (11)

  1. Johan Ericsson says:

    Just a guess, do you need to call the base class version of Finalize? or does it get called automatically. For that matter, do you have to call the base class version of Dispose?

  2. Tom Welch says:

    The Garbage Collector is not going to finalize the object in any known amount of time. If the resource you have ahold of is a file or some object that is locked by your reference to it then you can cause major problems by leaving it around until the GC feels like Finalizing thus freeing the resource.

  3. name says:

    That is true, but it doesn’t explain the syntax. I was under the impression that the traditional destructor syntax and the Finalize method were interchangable (the former used to appease C++ programmers that move to C#).

  4. Steve Maine says:

    What if Dispose() throws an exception? Then your finalizer method would prematurely exit, and the memory would never be reclaimed.

    Best practice would be to wrap Dispose in a try-catch block, so it could never exit via an exception. This would prevent finalization exceptions from orphaning your object. In practice, this is something that’s likely to be forgotten.

    That’s why, if I remember correctly, the C# compiler expands the desctructor syntax and inserts the try-catch structure for you automatically.

    Richter has a good discussion of this in Advande .NET Framework Programming.

  5. Tom Welch says:

    Well, I would venture to guess that the problem is that an explicit call to Finalize would invoke this.Dispose(false). By doing so, "this" gets referenced again thus preventing the garbage collecter from considering the object ready for deletion. By forcing the destructor syntax you do two things.

    1. Guarantee that no code will ever call the function explicity

    2. The compiler can inject code deliberately which causes the new reference to _not_ cause the object to stay alive.

  6. Fred says:

    You don’t call Finalize on your base class. Also, what Steve said… no exception handling.

    Richter’s book on .NET is good. By the way, Richter voices the opinion that the C# team should not have used the destructor syntax because C++ programmers believe that implies deterministic destruction.

    I’m not sure I agree with Richter’s logic, because you can’t create value types on the stack and obviously there’s no "delete" keyword in C#, so there’s no reason for C++ programmers to believe they have any control over when the "destructors" are called.

  7. Fred says:

    oops, should read "can’t create reference types on the stack"

  8. Please read my weblog to read what’s wrong with C# finalization. (Click my name to get there).

    In short:


    So what’s wrong with the C# destructor syntax? I think it encourages the mistake of thinking of Finalize as a destructor (and thus using it to cleanup other managed objects). Also, a "feature" of the C# destructor is that it always call the base class Finalize method. I hope I’ve shown that this isn’t very useful.

    Anders agreed with me. "In retrospect we probably shouldn’t have done that." (paraphrased from memory).


  9. Niall says:

    Other people have pointed out the problems: exception handling and calling base. Wrt these problems, I can see the advantage of C#’s implementation of finalizers.

    Was the "~" syntax chosen because of the partial similarity to C++ destructors (base destructor is called automatically)? I’m wondering how many people using C# who don’t have any C++ experience would see the C++ style syntax and realise this is what the behaviour would be. However, the help file for C# destructors (which I probably should have read first) does make it clear how they behave.

    Anyway, thanks for the enlightenment!


  10. What do you think of the role of :

    – Dispose : object management, i.e. releasing objects that the class won’t need anymore after it has done its job, for instance files, printers, etc

    – GC : memory management

    As far as I know (I’m not a C++ expert), you know when a destructor is called (i.e. the memory management and object management), but in C# you don’t know when Finalize is called. Since you don’t know when Finalize is called, you can’t bet on Finalize to do your object management.

    So, in the code example, I would not call Dispose from Finalize. I’d make an explicit call to Dispose when MyClass has done its job.

Skip to main content