I <3 Steve McConnell*
Coding Horror
programming and human factors
by Jeff Atwood

July 26, 2004

Just Say No to Finalization!

I am working with some classes that wrap unmanaged APIs, so I have to be concerned with releasing the resources associated with these APIs-- eg, the IDisposable interface. I was a little confused about the distinction between Dispose() and Finalize(), and in my research I found this article by Brent Rector of Wintellect:

In a worst-case scenario, your object's Finalize method won't run until your process terminates gracefully. (Actually, the real worst case is that it never runs at all because the process terminates abnormally.) Shortly thereafter, non-memory resources will be released anyway, so the Finalize method served no real purpose other than to keep the application from running as fast as it otherwise could.

Just say No to Finalize methods!

It's a good point. In a true worst case scenario-- unhandled exception time-- you won't get any benefit from Finalize. So, given the (evidently) large performance penalty of Finalize, why bother? I tend to agree. However, the best practice according to Microsoft is, if you implement IDispose, you should also implement a Finalizer:

    Private _IsDisposed as Boolean = False

    ''' <summary>
    ''' public Dispose method intended for client use
    ''' </summary>
    Public Overloads Sub Dispose() Implements IDisposable.Dispose
        Dispose(False)
        GC.SuppressFinalize(Me)
    End Sub

    ''' <summary>
    ''' common Dispose method; can be called by client or the runtime
    ''' </summary>
    Protected Overridable Overloads Sub Dispose(ByVal IsFinalizer As Boolean)
        If Not _IsDisposed Then
            If IsFinalizer Then
                '-- dispose unmanaged resources
            End If
            '-- disposed managed resources
        End If
        _IsDisposed = True
    End Sub

    ''' <summary>
    ''' called by the runtime only, at garbage collection time
    ''' this protects us if the client "forgets" to call myObject.Dispose()
    ''' </summary>
    Protected Overrides Sub Finalize()
        Dispose(True)
    End Sub

It's all rather contradictory.

Posted by Jeff Atwood    View blog reactions

 

« DEVELOPERS^3 Grand Unification Theory »

 

Comments

Jeffrey Richter's "Applied Microsoft .NET Framework Programming" has a very good treatment of this issue.

Here's my two-pennorth:

Sure, there's an overhead attached to stuff that does finalization, but you can see in your sample dispose method how it's dealt with. When you explicitly call your dispose method, you clean up your resources, and then suppress finalization, thereby clawing back most of your Finalize-caused performance drop.

I suppose the *allocation* of a finalizable object is slower than for a non-finalizable object, but that's because for the non-finalizable object, allocation is just incrementing a pointer. OK - can't get much faster than that, but who cares? If you've got a bunch of external resources to get started up anyway, there's not much point in discussing the theoretical possiblity of a "for free" allocation.

Dominic Cronin on August 8, 2004 12:00 AM

I actually own that book, and I've never gotten around to reading it. I'll check that section out. Jeffrey Richter, what the hell does that guy know anyway? ;)

I think, in general, one should avoid implementing IDisposable unless you *have* to. According to Paul Wilson, the dataset implements IDisposable, but ONLY because of some freakish side effect of inheritance-- in other words, it doesn't actually do anything useful in the finalization, which sort of devalues the rule "if implemented, must use"

http://weblogs.asp.net/pwilson/archive/2004/02/14/73033.aspx

Jeff Atwood on August 8, 2004 12:03 AM







(hear it spoken)


(no HTML)




Content (c) 2008 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved.