Sunday 7 February 2010

If a class implements IDisposable then an instance of that class should be wrapped in a “using” (c# or the vb equivalent) which guarantees dispose… otherwise Dispose should always be called explicitly; if dispose is implemented the developer meant that specific cleanup logic should always execute. Usually Dispose is implemented for cleaning un-managed resources, rather than managed.

Where Close* is also implemented, then Dispose should always call Close as part of the dispose implementation and because we’re all cynics reflector is our friend – see reflected code snippets for SQL Data Reader and SQL Connection below.

Obviously with view of connection pooling, closing a connection doesn’t necessarily mean that the resource is free

Framework2.0 SqlConnection

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

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}


Framework2.0, SqlDataReader

public void Dispose()
{
    this.Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        this.Close();
    }
}


BTW whilst I’m in favour of understanding the inner working of objects that you code against, it’s my opinion that better code is explicit code, so I would be in favour of explicit close() for all instances where close() should be called, even if I know – as a developer – that close() is implicit.

I believe this also guards against future changes to the framework, in later versions.



* Close would usually be implemented because it’s (conceptually) cheaper to re-open a closed connection (for example) than allocate a new one which would also appear to be the consensus.