9

I have been programming in .NET for four years (mostly C#) and I use IDiposable extensively, but I am yet to find a need for a finaliser. What are finalisers for?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
open-collar
  • 1,404
  • 1
  • 16
  • 22
  • 5
    Btw, I'm English, and I've found that it's a *really* *really* good idea to get into the habit of spelling "finalize" and "initialize" with a z, not an s. Otherwise, you can never find the bloody things when you search for them in documentation! – Steve Jessop Apr 20 '09 at 14:38
  • 1
    @onebyone - ditto. Likewise, Color... it used to cause me irritation, but now I just consider them the technical term for the industry, and get the job done ;-p – Marc Gravell Apr 20 '09 at 14:49
  • I have been trying to train myself - I use it in documentation and public facing code, but I just can't bring myself to do it in "real life". – open-collar Apr 20 '09 at 15:01

5 Answers5

12

A finalizer is a last ditch attempt to ensure that something is cleaned up correctly, and is usually reserved for objects that wrap unmanaged resources, such as unmanaged handles etc that won't get garbage collected.

It is rare indeed to write a finalizer. Fortunately (and unlike IDisposable), finalizers don't need to be propagated; so if you have a ClassA with a finalizer, and a ClassB which wraps ClassA, then ClassB does not need a finalizer - but quite likely both ClassA and ClassB would implement IDisposable.

For managed code, IDisposable is usually sufficient. Even if you don't clean up correctly, eventually the managed objects will get collected (assuming they are released).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
4

Finalizers are only for freeing unmanaged resources like GDI bitmap handles for example. If you don't allocate any unmanaged resources then you don't need finalizers. In general it's a bad idea to touch any managed object in a finalizer because the order of finalization is not guaranteed.

One other useful technique using a finalizer is to assert that Dispose has been called when the application is required to do so. This can help catch coding errors in a DEBUG build:

void Dispose()
{
  GC.SuppressFinalize(this);
}
#if DEBUG
~MyClass()
{
  Debug.Fail("Dispose was not called.");
}
#endif
JayMcClellan
  • 1,601
  • 1
  • 11
  • 10
2

Finalizers are meant as a mechanism to release resources not controlled by garbage collector, like an unmanaged handle. While Dispose might do it, it isn't guaranteed that the consumer will call it.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
1

Finalizers are for cleaning up resources if they were not disposed.

IE, nothing enforces that you ever call Dispose(), but Finalizers are called automatically by the garbage collector.

This functionality should not be relied upon, as there is no guarantee when (or if) garbage collection will get to your object.

Jason Coyne
  • 6,509
  • 8
  • 40
  • 70
1

Wikipedia says:

...a finalizer is a piece of code that ensures that certain necessary actions are taken when an acquired resource... is no longer being used [because the owning object has been garbage collected]

And if you're not using a finaliser when you're writing IDisposables you've quite possibly got memory leaks, because there's no guarantee an owner is actually going to call Dispose().

MS themselves recommend you write something similar to this into your implementers:

    public void Dispose()
    {
        this.Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.isDisposed)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
        //Dispose of resources here
        this.isDisposed = true;
    }

    ~DisposableSafe()
    {
        this.Dispose(false);
    }

    private bool isDisposed = false;

Personally, I can't stand the copy-paste so I tend to wrap that in an abstract class for reuse.

annakata
  • 74,572
  • 17
  • 113
  • 180
  • Unless your class directly deals with *unmanaged* resources then you probably don't need a finaliser. Managed resources should eventually be dealt with by the GC, regardless of whether or not the user calls Dispose. – LukeH Apr 20 '09 at 14:57
  • This is waht made me write "possibly" instead of "probably" and I worried about that. But it's not quite true anyway. If your class implements some other IDisposable then you have a responsibility to call Dispose() on that too. And as it goes, from MSDN "The primary use of this interface is to release unmanaged resources." – annakata Apr 20 '09 at 15:29