114

What is the difference, if there is one, between a destructor and a Finalize method in a class?

I recently discovered that Visual Studio 2008 considers a destructor synonymous with a Finalize method, meaning that Visual Studio won't let you simultaneously define both methods in a class.

For example, the following code fragment:

class TestFinalize
{
    ~TestFinalize()
    {
        Finalize();
    }

    public bool Finalize()
    {
        return true;
    }
}

Gives the following error on the call to Finalize in the destructor:

The call is ambiguous between the following methods or properties: 'TestFinalize.~TestFinalize()' and 'TestFinalize.Finalize()'

And if the call to Finalize is commented out, it gives the following error:

Type 'ManagementConcepts.Service.TestFinalize' already defines a member called 'Finalize' with the same parameter types

Sam
  • 7,252
  • 16
  • 46
  • 65
Jeff Leonard
  • 3,284
  • 7
  • 29
  • 27

3 Answers3

76

A destructor in C# overrides System.Object.Finalize method. You have to use destructor syntax to do so. Manually overriding Finalize will give you an error message.

Basically what you are trying to do with your Finalize method declaration is hiding the method of the base class. It will cause the compiler to issue a warning which can be silenced using the new modifier (if it was going to work). The important thing to note here is that you can't both override and declare a new member with identical name at the same time so having both a destructor and a Finalize method will result in an error (but you can, although not recommended, declare a public new void Finalize() method if you're not declaring a destructor).

Lloyd
  • 29,197
  • 4
  • 84
  • 98
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
76

Wikipedia has some good discussion on the difference between a finalizer and a destructor in the finalizer article.

C# really doesn't have a "true" destructor. The syntax resembles a C++ destructor, but it really is a finalizer. You wrote it correctly in the first part of your example:

~ClassName() { }

The above is syntactic sugar for a Finalize function. It ensures that the finalizers in the base are guaranteed to run, but is otherwise identical to overriding the Finalize function. This means that when you write the destructor syntax, you're really writing the finalizer.

According to Microsoft, the finalizer refers to the function that the garbage collector calls when it collects (Finalize), while the destructor is your bit of code that executes as a result (the syntactic sugar that becomes Finalize). They are so close to being the same thing that Microsoft should have never made the distinction.

Microsoft's use of the C++'s "destructor" term is misleading, because in C++ it is executed on the same thread as soon as the object is deleted or popped off the stack, while in C# it is executed on a separate thread at another time.

Pacerier
  • 86,231
  • 106
  • 366
  • 634
Kenzi
  • 1,059
  • 8
  • 10
  • I would argue that such a distinction between the destructor and finalizer is an important one to make. However, only those that care about what's going on under the hood would care about said distinction. – Kyle Baran May 11 '14 at 03:54
  • 1
    Also note ECMA-334 has explicitly disambiguated "destructor" and "finalizer" formally, long ago. I don't know why MS still insists on the misleading term in their specifications. – FrankHB Aug 08 '16 at 02:44
  • At least from working with Mono, C# is actually modeled after C++, and most native C# objects are C++ objects. The way the compiler that compiled Mono works dictates how those C++ objects are destructed, and likewise, how C# object finalization propagates down to C++ and calls those destructors. The distinction makes sense under the hood, but it still doesn't really apply to C# itself. – Kenzi Mar 29 '17 at 15:03
21

Found here: http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  1. Destructor

    They are special methods that contains clean up code for the object. You can not call them explicitly in your code as they are called implicitly by GC. In C# they have same name as the class name preceded by the ~ sign. Like-

    Class MyClass
    {
    
    ~MyClass()
    {
    .....
    }
    }
    

    In VB.NET, destructors are implemented by overriding the Finalize method of the System.Object class.

  2. Dispose

    These are just like any other methods in the class and can be called explicitly but they have a special purpose of cleaning up the object. In the dispose method we write clean up code for the object. It is important that we freed up all the unmanaged recources in the dispose method like database connection, files etc. The class implementing dispose method should implement IDisposable interface.A Dispose method should call the GC.SuppressFinalize method for the object it is disposing if the class has desturctor because it has already done the work to clean up the object, then it is not necessary for the garbage collector to call the object's Finalize method. Reference: http://msdn2.microsoft.com/en-us/library/aa720161(VS.71).aspx

  3. Finalize

    A Finalize method acts as a safeguard to clean up resources in the event that your Dispose method is not called. You should only implement a Finalize method to clean up unmanaged resources. You should not implement a Finalize method for managed objects, because the garbage collector cleans up managed resources automatically. Finalize method is called by the GC implicitly therefore you can not call it from your code.

    Note: In C#, Finalize method can not be override, so you have to use destructor whose internal implementation will override the Finalize method in MSIL.But in the VB.NET, Finalize method can be override because it does support destructor method.

Update: Interesting semi-related thread here.

Community
  • 1
  • 1
Andrew Siemer
  • 10,166
  • 3
  • 41
  • 61
  • 1
    `You should only implement a Finalize method to clean up unmanaged resources` : you put it in Finalize. Same with Dispose ? – hqt May 27 '12 at 04:00
  • @hqt: Cases where one should implement `Dispose` vastly outnumber those where one should implement a finalizer. Implement `Dispose` if it is likely that an instance of the class or a derived class will be the last thing to either directly own an unmanaged resource, or directly own the last thing to directly own an unmanaged resource, or directly own the last thing to directly own etc. Only implement `Finalize` for resource cleanup if one's class directly owns an unmanaged resource and almost nothing else--a much narrower scenario. – supercat Jun 11 '12 at 20:15
  • @hqt: If one a class would directly own unmanaged resources and also holds references to other objects, the unmanaged resources should generally be split off into their own finalizable class (which should ideally not hold any strong references to anything else), meaning the class which holds references to other objects would only own "things which directly own unmanaged resources", rather than owning the resources themselves, and would thus not need a finalizer. – supercat Jun 11 '12 at 20:17