Finalizer C#. Why Finalizer not calling?

304 Views Asked by At

Why is my finalizer not being called?

using System;

class Program
{
    static void Main(string[] args)
    {
        Test test = new Test();
    }
}

class Test
{
    public Test()
    {
        Console.WriteLine("Start");
    }   

    ~Test()
    {
        Console.WriteLine("End");
    }
}

I searched on the Internet, I did not find anything suitable. I was expecting a console output "End" at the end.

3

There are 3 best solutions below

3
On BEST ANSWER

There's no requirement for all finalizers to be executed when the process terminates. Finalizers should not be used for things that absolutely must happen.

You can call GC.WaitForPendingFinalizers() if you really want to - along with other GC. methods to prompt garbage collection in the first place - but doing so in production code is usually a sign of a problematic design. Finalizers just aren't designed to work this way. They should be extremely rare in C# code in general; in my experience they're usually used to log warnings of "You appear not to have disposed of this, and you really should do - clean up will happen eventually, but this is something that should be cleaned up more eagerly."

0
On

I would recommend to read the "Everything you know is wrong" articles by Eric Lippert (Part One, Part Two). In short finalizers are tied to the GC and it is not guaranteed that finalizer will ever be called.

Another issue is covered in this answer - even if you will force the GC it still may not result in finalizer being called due to JIT possibly prolonging the lifetime of the object (i.e. it is not collected).

The general rule of thumb - do not use finalizers (implement if needed so they can be "last resort" if developer will do something incorrectly) and for deterministic resource clean up use the IDisposable pattern.

Read more:

0
On

Finalier can be called, but not necessary will be called: if Garbage collector doesn't collect Test instance, then finalizer will not be called. In case you want to guarantee the call (e.g. if you want to free some resources), you should implement IDisposable interface:

https://learn.microsoft.com/en-us/dotnet/api/system.idisposable?view=net-7.0

using System;

class Program
{
    static void Main(string[] args)
    {
        // Note "using"
        using Test test = new Test();
    }
}

// Note IDisposable and abscence of finalizer 
class Test : IDisposable
{
    public Test()
    {
        Console.WriteLine("Start");
    }   

    protected virtual void Dispose(bool disposing) 
    {
        Console.WriteLine("End");
    }

    public Dispose() {
        Dispose(true);
    }
}