Understanding when to use a Finalizer in your .NET class


A common problem we see when moving to .NET all revolves around the finalizer.  There are a few reasons that this happens:

  • Developers move from C/C++ to C# and are used to created classes with a constructor and destructor.
  • Developers don’t understand when they need to implement Dispose or Finalize and thus create them when they aren’t needed.

Finalization – what is it?

So what is Finalization and why is this such an important thing to understand?  Well, there is a good description of it found here.  Basically it is a way to make sure some code runs when an object gets cleaned up.

Why is it necessary?

If an object holds onto any unmanaged resources, such as file handles, sockets or database connections, the object is responsible for cleaning them up when it is destroyed.  This only applies to unmanaged resources!

I would very strongly recommend that you read the documentation for the Finalize object very carefully before you use it.  The things to watch for are:

  1. If you use an unmanaged object and hold a reference to it, you must implement a Finalizer to allow that unmanaged object to be cleaned up.  Otherwise you will leak unmanaged (heap) memory.
  2. If you create a Finalize method (~Class in C#), even if it is empty, this will put the object on the finalize queue.
  3. If you have a Finalize method, don’t try to clean up managed objects from it.  That is why most Finalize methods call Dispose(false).  So they don’t clean up any managed objects.  This is because finalized can happen in any order and just cause you hold a reference to an object, doesn’t mean it hasn’t been cleaned up already.

Why is a Finalize method bad?

So now we know how we should use the finalizer, but why is it so important to do it correctly?  So items 1 and 3 above are pretty explanatory as to why you would want to do that.  So what is wrong with #2?

If an object has a finalizer, it will be placed in the FinalizationQueue and is subject so some additional clean-up.  Once the object is no longer referenced on a thread or from a global reference, the next time the Garbage Collector (GC) runs, it will see this object is ready to be collected.  But it can’t collect it yet.  It has to let the Finalizer run first.  So the GC will finish collecting, then the Finalizer will Finalize the object, and then another GC collection will occur.

This can have a huge affect on performance as you should remember that all managed threads will be stopped waiting on the GC and then the GC will be stopped waiting on the Finalizer thread.

There is a lot more data out there about Finalization so I encourage you to read about it as much as possible so that you use it in the best way possible.

kick it on DotNetKicks.com

Comments (9)

  1. You’ve been kicked (a good thing) – Trackback from DotNetKicks.com

  2. If you are going to use a finalizer in your .NET class, be sure to read this post so that you understand

  3. Your last few sentences are slightly inaccurate.  When GC occurs, the object will be placed on the finalizer thread’s queue.  At this point GC doesn’t wait for the finalizer thread to run the finalizer – it completes normally.  When the finalizer thread runs the finalizer and another GC occurs, the object will be collected.  So the primary thing to note is that GC doesn’t wait for the finalizer.

  4. Finalization is one of the most complicated and obscure areas of .NET. Most developers don't actually

  5. Link: Understanding when to use a Finalizer in .NET

  6. GProssliner says:

    The GC doesn’t wait for the Finalizers to complete!

    The CLR creates a own Thread for performing Finalization. You may use GC.WaitForPendingFinalizers() to join the Finalization-Thread.

    What is also very important for the cost of finalization is that Objects waiting for finalization are still considered as Root-References for the GC, so also Objects references by them will not get collected (assuming Strong-References). So it take at least one more Collection to get rid of them.

    If a Finalizer is implemented “just for safty” (for the case the someone doen’t call Dispose in all Code-Paths) – System.ComponentModel.Component is an example of that – you shall call GC.SuppressFinalize(this); within you Dispose() Implementation. This would prevent that the Object will be added to the FReachable Queue when the GC is considering the Object as Garbage.

  7. tomchris says:

    Sasha,

    Very true, I corrected the post on that.  Thanks for finding it.

  8. tomchris says:

    GProssLiner, thanks for the additional notes.  All very important.  I corrected the mistake about the GC.  Thanks for finding it.

  9. So in a previous post, we talked about Understanding when to use a Finalizer in your .NET class so now