Dispose, Finalize and SuppressFinalize

food-drk-017

I got the following question recently.

What is the difference between Dispose and
SupressFinalize in garbage collection?”

The problem with this question is it assumes Dispose and SupressFinalize have similarities, which I’m sure is not what is being asked here.  So let’s rephrase it in terms that make sense.

I see three methods available to me in .NET that all seem to have something to do with garbage collection.  Can you explain what Dispose, Finalize, and SupressFinalize do and why I could use or call each one in my code?”

Now, that’s something we can answer.

A Brief History of Memory Management

Before we answer the question, we need to review how memory management works in .NET compared to historical languages such as C/C++.

In the old days, if an application allocated memory on the heap (generally done with the “new” keyword in CSharp) the application was also responsible for releasing the memory.  In languages such as C++, this was done with the “delete” keyword which triggered a call to a special method called a destructor.  If the object was holding on to memory or other resources, it was the destructor’s job to release those resources.

In .NET memory is deallocated for us using garbage collection.  We no longer call the destructor using anything like a delete keyword and the deallocation process happens at some point in time that is after the memory goes out of scope.  This might be immediately after the object goes out of scope or it could be hours or days.

Generally, this is not a problem, but what about an object that is holding on to additional resources that need to be freed up right away?

For that we have the Dispose() method.

Dispose is the new destructor.

While we don’t need a destructor to handle our memory, we do need something to release resources. This is why the IDisposable interface was created with one method that needs to be implemented called Dispose().

If your class allocates resources that need to be freed up that aren’t memory, you should implement the IDisposable interface on that class and implement the Dispose() method.  Inside that method, you would release any resources that the class may have created and not freed.

Dispose() will then automatically get called by Finalize()

When the garbage collector starts releasing memory, one of the things it will do is that it will go through your code and call Finalize() on each of the objects.  Finalize() will then call any dispose methods that are available.

This is done to protect the programmer from himself, not because it is expected.  Remember I said the memory will get freed up at some indeterminate point in the future but the Dispose() method was created so we could free up the resources right away?

What we really want to do is call Dispose() ourselves.  We call Dispose from our own code.  Finalize() only exists so that Dispose() will get called if we don’t.

And that’s where SupressFinalize() fits in.

If my code calls Dispose() then there is no reason for the Finalizer to run at all.  Without SupressFinalize() we would need to set a flag in our class indicating that Dispose() had already been called so that when Finalize() called it, we didn’t re-run the clean up code.

With SupressFinalize() we can just call SuppressFinalize() from within Dispose() and that will tell .NET to not run the Finalize method when it gets to our object.

Your call to SupressFinalize() should almost always look like

GC.SuppressFinalize(this);

but you can pass in any object instead of “this.”

Related Post

  • Dispose with UsingDispose with Using I'm sure that many of you already know that many of the objects in the .NET framework need to be disposed.  The most common of these are the windows objects and the stream objects. Of course th...
  • Stackalloc in CSharpStackalloc in CSharp In the last few weeks we've looked at several keywords from the CSharp language that allow us to deal with memory management directly.  Stackalloc is another keyword from that list. Before we l...
  • Making values nullableMaking values nullable First, a little history lesson. When .NET was first released, we had value types and object types.  The difference between the two is that you do not have to set aside memory for a value type b...
  • Advanced CSharp – unsafe modeAdvanced CSharp – unsafe mode One of the "advantages" of using CSharp instead of VB.NET is that if programmers want to, they have the option of bypassing the memory management of .NET and working with memory directly.  This is...
  • CSharp fixed keywordCSharp fixed keyword Since I've already mentioned my bias against using unsafe mode in this post: Advanced CSharp - unsafe mode I'll skip my normal rant about that.  Just suffice it to say they don't call it "uns...
  • Pingback: Dew Drop – July 9, 2009 | Alvin Ashcraft's Morning Dew

  • Mihail

    Just wonder what you think about this way of handling Dispose:

    #region IDisposable Members

    private bool _alreadyDisposed;

    ///
    /// Finalization code
    ///
    ~SelectSourceFilePresenter()
    {
    Dispose(false);
    }

    ///
    ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    ///
    ///2
    public void Dispose()
    {
    Dispose(true);
    GC.SuppressFinalize(this);
    }

    ///
    /// Disposal of resources, called by the destructor and Dispose()
    ///
    ///
    protected virtual void Dispose(bool isDisposing)
    {
    if (_alreadyDisposed)
    return;

    if (isDisposing)
    {
    // add resource cleanup here
    BrowseSelectionMade -= ViewBrowseSelectionMade;
    }

    _alreadyDisposed = true;
    }

    #endregion

    • Dave

      Without knowing what your code is doing specifically, it seems over architected to me. Why have the private member _alreadyDisposed, at least where it is? Does the same thing as Suppress and if your virtual dispose is called by the finalizer (~()), your BrowserSelectionMade never gets called.

      The point of the finalizer is that it calls dispose IF dispose doesn’t get called. It’s a fail safe. Your code depends on the programmer having done things right in the first place.

      And I’m assuming your

      BrowseSelectionMade -= ViewBrowseSelectionMade;

      code is unwiring an event handler. There is no reason to do that!

  • Mihail

    My understanding is that in a Dispose method it’s safe to clean up ALL resources that an object is holding onto (managed objects or native resources). In a finalizer it is only safe to clean up objects that are not finalizable – the finalizer should only be releasing native resources.
    True that I don’t need specifically in this case, to follow this pattern.
    Why not unwiring an event handler?

    • Dave

      No, finalize exist solely to call dispose for the programmer who forgot to OR in the very rare case where the finalization process needs to be intercepted, for example object pooling.

      Dispose exist to release managed resources (GDI handles, File handles, managed code pointers, etc) or to set variables in the class to NULL in the very rare case that not doing so would cause a memory leak (circular references
      might be an example here but even then, .NET handles that condition pretty well on it’s own.

      Everything else is handled by .NET, including unwiring event handlers.