tags:

views:

78

answers:

4

In other words,

class Foo
{
    object obj;
    Foo() { obj = new object(); }
    ~Foo() { obj.ToString(); /* NullReferenceException? */ }
}
A: 

If this is a concern, then it's probably better to dispose than finalize.

Joel
But what if the user of my class doesn't call `Dispose`? I have to have a plan for that, haven't I?
CannibalSmith
+6  A: 

From Object.Finalize:

The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already finalized when the finalizer of Object A starts.

In short, you can't make any assumptions about the state of referenced objects during a finalizer.

In virtually all circumstances, the logic implemented in a finalizer belongs in the Disposable pattern. This is an example of how to correctly implement the pattern in .NET using the IDisposable interface.

public class MyClass : IDisposable
{
    private bool _disposed;

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

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if(disposing)
            {
                // Release unmanaged resources.
            }

            // Release managed resources (Streams, SqlConnections, etc.)
        }

        _disposed = true;
    }
}

In the unlikely event you're working with unmanaged resources, have a look at this article for how to implement IDisposable with a finalizer:

MDSN: Implementing Finalize and Dispose to Clean Up Unmanaged Resources

Programming Hero
Just because you implement `IDisposable` does *not* mean you should implement a finalizer. In fact, you almost never want to implement a finalizer. However, if you do implement a finalizer you should also implement `IDisposable`.
Scott Dorman
You only want a finalizer if your object directly contains unmanaged resources. You should also be wrapping your unmanaged resource handles into objects like `SafeFileHandle` so the resulting finalizer does not place undue load on the GC.
280Z28
I agree that you don't want to implement a finalizer unless you're handling unmanaged resources. I had hoped overloading `Dispose` would make that clear, but I'll re-do my code example to work with just the managed resources scenario. Just for you guys ;)
Programming Hero
@Programming Hero: Actually, your original code example was spot on if you just removed the finalizer. To properly implement the Dispose pattern, you do want a `public virtual void Dispose(bool disposing)` method which contains all of your disposal logic (as you had in your original code) and the `IDisposable.Dispose()` method implementation should simply call that one (again, as you had in the original example). You just didn't need to implement the finalizer.
Scott Dorman
Curiously, why would you want the overloaded Dispose if you aren't handling unmanaged resources? Is it just as an extension point in the unlikely event somebody wants to extend your class with unmanaged resources?
Programming Hero
+3  A: 
stmax
A good quote and article.
Programming Hero
So the answer is: it's safe *if* you know *for sure* that the referenced object is also referenced by other live objects.
CannibalSmith
+1  A: 

In general, you don't want to implement finalizers on your objects. If you need to perform resource cleanup of managed objects, you want to do that in Dispose and properly implement the Dispose pattern.

If you do end up implementing a finalizer, you only want to access unmanaged resources.

Scott Dorman