Monday, July 28, 2008

Paper, Plastic or Wood?

I find stories about recycled plastic based building materials encouraging.  It's ironic that plastics, which can take decades or centuries to decompose, have been so heavily used in the products with transient lives, but wood which decomposes much more readily is the primary component of homes, which we at least hope will last much much longer.  The plastic bag for example, which on average is probably used about 30 minutes a piece.  Even computers and electronics, which at best will last ten years, usually less, before being obsolete.

There were many other factors which have lead to the current state, of plastics being part of the most disposable products, but I think a number of them are changing and I won't be at all surprised to find that some of the intrinsic characteristics of plastics, rather than the incidental characteristics of early plastics, will play a greater role in their future.

Thursday, July 24, 2008

Using Dispose, Finalizers and IDisposable

Garbage collection does not solve all problems. Many of them yes, but not all, which is why .NET has finalizers AND IDisposable. There is a fairly simple pattern here, but it’s often misunderstood and misused.

To understand the pattern, you should first understand the difference between a managed and an unmanaged resource. A managed resource is simply a resource that is managed by the runtime. The runtime guarantees you that it will destroy that resource, at some time. It does not make any guarantee as to when. This caveat is the reason IDisposable exists. If you’re a Java developer, it’s possible that IDisposable seems alien, but it really shouldn’t. Java applications have the same needs as .NET applications in this area, but there isn’t a standard pattern. Instead there are informal patterns like cleanup().

An unmanaged resource is everything not managed by the runtime. Common examples of unmanaged resources are file handles, COM objects, or network sockets. This is where developers sometimes get confused because the common examples refer only to the native resource, not any wrappers. A class that wraps an unmanaged resource is not by association an unmanaged resource, it is a managed resource. So FileStream, DbConnection and COM Interop objects are not unmanaged resources.

The distinction is very important when you write any code that may be called by a finalizer. The common pattern for Dispose is documented at:

http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx

What it says is:

    public void Dispose() 
{
Dispose(true);

// Use SupressFinalize in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
// If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
if (!_disposed)
{
if (disposing) {
// Release managed resources
}

// Release unmanaged resources
// Also, it is okay (though not truly necessary)
// to set managed resources to null.
_disposed = true;
}
}

If you use a finalizer, it shouldn’t do anything more than call Dispose(false). A lot of developers make the mistake of assuming they must create a finalizer when implementing IDisposable, but that isn’t true, and there is a minor downside if you don’t need it. If a user of your class fails to call Dispose, then the object will remain in the finalization queue which impacts performance of the GC. That’s pretty minor because if you implement IDisposable callers should call Dispose and SuppressFinalize will avoid that penalty. But really the finalizer is unnecessary since it can always be added later and still call Dispose(false).

That has the downside that if you declare a finalizer on a subclass and base class (or more) then you may end up at if (!_disposed) more than once. Compared to the harm to the GC cycle of the other option I think this is the preferable choice. Just be consistent so that no one expects a finalizer to already exist when it doesn’t.

Examples

There are plenty of examples of good IDisposable implementations on the Internet, so I won’t waste time on another, instead, what I’ll supply is some of the common mistakes.

The most common is attempting to release a managed resource from the finalizer (or code called from the finalizer). For example:

    ~DbConnectionWrapper()
{
_dbConnection.Dispose();
}

Or the more common:

    protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
_dbConnection.Dispose();
_dbConnection = null;
_disposed = true;
}
}

What’s wrong with these examples? Well the first hint is that if you ever call another objects Dispose from a finalizer, or from the unmanaged section of Dispose(bool disposing), then you’ve done something wrong. You might be tempted to believe you are providing extra safety, but you’re losing it instead. What’s the current state of _dbConnection at this point? Assuming DbConnectionWrapper has the only reference then it will be in the process of being finalized in the same GC as DbConnectionWrapper. You cannot know then whether it has already been finalized itself since the GC does not garauntee an order than finalizers will be executed. As well, what value does calling Dispose at this point provide? The object is already in the process of being finalized, so it’s at best redundant. The correct implementation would be:

    protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_dbConnection.Dispose();
}

_dbConnection = null;
_disposed = true;
}
}