Why Finalize method not allowed to override

Posted on

Problem :

I am new to .net ..and i am confused with the destructor mechanism in C# ..please clarify

In C# destructors are converted to finalize method by CLR.
If we try to override it (not using destructor ) , will get an error
Error 2 Do not override object.Finalize. Instead, provide a destructor.

But it seems that the Object calss implementation in mscorlib.dll has finalize defined as protected override void Finalize(){} , then why cant we override it , that what virtual function for .

Why is the design like that , is it to be consistent with c++ destructor concept.

Also when we go to the definition of the object class , there is no mention of the finalize method , then how does the hmscorlib.dll definition shows the finalize function.
Does it mean that the default destructor is converted to finalize method.

public class Object
{     

    public Object();
    public virtual bool Equals(object obj);        
    public static bool Equals(object objA, object objB);       
    public virtual int GetHashCode();       
    public Type GetType();      
    protected object MemberwiseClone();  
    public static bool ReferenceEquals(object objA, object objB);
    public virtual string ToString();
}

Solution :

am new to .NET and i am confused with the destructor mechanism in C#. Please clarify.

Sure. I agree that it is confusing.

In C# destructors are converted to finalize method by CLR.

Correct. Well, I’d say that this is done by the C# compiler, not the CLR, but I understand what you mean.

If we try to override it (not using destructor ) , will get an error “Do not override object.Finalize. Instead, provide a destructor.”

Correct.

it seems that the Object class implementation in mscorlib.dll has finalize defined as protected override void Finalize(){}

Correct.

then why can’t we override it? That’s what a virtual function is for.

Because then there would be two ways to write a destructor. That would be confusing. We want there to be only one way to write a destructor.

Why is the design like that? is it to be consistent with c++ destructor concept?

That is one reason, yes. There are other reasons. Here are a few:

  • By logically separating the concepts of “destructor” and “override the finalize method” we make it possible to implement destructors via some other mechanism in other environments. This hasn’t happened yet, but it could happen that in the future we write a version of C# that, say, is for building device drivers in an environment that has different garbage collector semantics than the standard CLR semantics. In that environment the semantics of the destructor might be more like those of the C++ destructor and less like a GC finalizer.

  • Finalizers are very very special methods. You cannot call them like regular methods; only the garbage collector can call them. They have different exception handling rules. They must ensure that base class finalizers are called strictly after derived class finalizers. They are so special that it seems dangerous to expose them as methods like any other. If you have a method just sitting there that you can call, that you can put anything you want into, and so on, it makes it easy to forget how special a finalizer is. Having a special syntax emphasizes that this is special code.

Also when we go to the definition of the object class, there is no mention of the finalize method , then how does the mscorlib.dll definition shows the finalize function .

Suppose we showed a method in the object browser called MagicUnicorn, and if you tried to call it or override it, you’d get an error saying “don’t do that!”. Why bother to show the MagicUnicorn method at all if you can’t do anything with it? That’s just unhelpful noise.

Now, if you disassemble mscorlib then of course there really is the special Finalize method there.

Does it mean that the default destructor is converted to finalize method.

Yes.

‘Why is it so?’
By a design decision. Probably to match up with C++ but it really doesn’t matter.

how does the hmscorlib.dll definition
shows the finalize function

There probably is a special intervention in the C# compiler. Again, it makes no practical difference.

If you really need a finalizer, write a destructor. More important: you almost never need to.

To see how arbitrary this choice is: in VB you can override Finalize. And those two languages can quite happily use (and inherit) each others types.

Does it mean that the default destructor is converted to finalize method

Yes, the default (and only) destructor syntax in C# is compiled as the Finalize method. This was likely to provide a familiar syntax to C++ developers. See Destructors on MSDN for more information.

To override Finalize(), you must use the finalizer syntax. The CLI uses fixed names for certain things internally, such as all instance constructors named exactly .ctor, and all static constructors named .cctor. When the C# compiler writes the output assembly, it makes sure to use proper names for items it emits, which includes writing the destructor as having the name Finalize() instead of ~T(). Compilers for other .NET languages must follow these same rules for their own semantics as well.

class A
{
    ~A() { /* ... */ }
}

For the when and how of finalizers, look for the many other questions here that deal with finalizers and IDisposable.

In C++, you need the destructor to be virtual. The reason is, this is how it is invoked

A a = new B() //where B derived from A
delete a;

A bit rusty on C++, so forgive me if I am wrong. But see, the delete is passed a reference that may be of a base class.

In C#, you do not invoke the finalizer. It is invoked internally by the garbage collector. There is no reason a garbage collector would be interested in what kind of references were assigned earlier, and gets directly to the object 🙂

Now, the finalizer just gets the syntax from C++. Hence the confusion.

What other people are saying is, you usually don’t need finalization. This is why.

If you implement IDisposable, you can take help of the “using” statement to decide the scope of the variable and dispose it when you want. With Finalization, the decision of when exactly the method will be called is taken by the GC. That means, if you need to release resources, the timing may be wrong.

Hope this helps.

Leave a Reply

Your email address will not be published. Required fields are marked *