Preza8
Preza8

Reputation: 399

Using a finalizer to do logic, when is it called

Can a class's finalizer be used for anything else than freeing resources? I read that it is called when the GC wants to remove the object from memory, which is very inspecific (I can see why but that limits its usage). Is it possible to reliably use the finalizer to do logic that is supposed to happen when a variable goes out of scope? If the finalizer is not fit for this, how can it be achieved?

My idea is basically the same as a destructor of an object that in c++ would be allocated on the stack, therefore its destructor has to be called when it goes out of scope. Or is there a way to force an object into the stack, so that it would behave the same way? Or maybe a using(...) block and the dispose-related methods can be used to achieve something like this?

Upvotes: 1

Views: 329

Answers (2)

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23228

In C# you don't need to use the finalizer directly. It's being called by GC to clean up only unmanaged resources, if any. Technically, the finalizable object is added to a separate queue and being finalized in a separate thread before being garbage collected. However, it's a vary basic flow and you don't have to rely on it.

Eric Lippert has written two very nice articles about finalizers under the hood, this and this, refer to them to see a possible pitfalls here. Finalizers are called in a non-deterministic order, you should never perform any logic depends on other objects inside finalizer.

For you purposes you can implement IDisposable interface and clean up the resources explicitly, have a look at MSDN guide for details.

The very simple sample is below

public class MyResource : IDisposable
{
    // managed resource this class uses.
    private readonly Component _component = new Component();
    private bool _disposed;

    public void Dispose()
    {
        if (!_disposed)
        {
            // Dispose managed resources.
            _component.Dispose();
            _disposed = true;
        }
        //tell CLR to prevent finalization, since it's already done
        GC.SuppressFinalize(this);
    }
}

If your class wraps only managed resources, you don't need to use a finalizer, you just implementing a Dispose() method to clean up a managed resources.

Object, implementing IDisposable, can be used in using statement, or in try/finally block, according to using an object that implements IDisposable

Upvotes: 1

Yennefer
Yennefer

Reputation: 6234

Besides the posted links, you are going against the design and you might end up in a lot of weird things if you keep on going this road.

If you want to replicate c++ RAII behavior, just use the using keyword with disposable resources.

C# 8 introduce the ability to declare using var variables,just syntactic sugar that syntactically make the code as closest as possible to c++ RAII.

Eric Lippert links explain what's going on under the hood, clearly this gives you an insight, but nothing there is contractual when leaving the designed road.

Upvotes: 1

Related Questions