blog.jj5.net (2003 to 2005)

Always calling dispose

Mon Oct 4 14:16:00 UTC+1100 2004

Categories:

I've written a few emails lately, and then decided not to send them.

I really don't like it when I do that. But I've been growled at for long posts once too often lately, and I'm either losing my nerve, or losing my faith in the intelligence of others ( take your pick; futility underlies each ).

I kind of liked this one though. So I'm gonna post it here rather than let it meet the same fate as all those other long posts that have been left to fade away in my drafts folder.

If you don't like it, you can suck my balls.

John.

--

David Crowell wrote:
> However we recently started using CoreLabs MySQL Direct .NET to talk
> with MySQL databases.  It seems to require the Close() call, yet Dispose
> seems to be unnecessary.  It's probably a bug that Dispose() isn't
> calling Close().

If anything the bug is in the SqlServer client, not the MySQL client.

If you have a 'connection' object then you would expect it to have an *interface* with specific 'open' and 'close' verbs defining a rigid implementation *contract*. That is, if you call Open() then you must guarantee to call Close(), etc.

This would have nothing to do with the IDisposable interface. In this case it's about the contract on the 'connection' interface.

On the other hand, when you have an interface like IDisposable whose contract is "optionally call if you need deterministic finalization of unmanaged resources" then calling 'close' from there would border on *insane*. Because if you do more than release unmanaged resources in there, and people start to depend on that, then you're locking yourself into maintaining a behavior that was not defined as part of the contract into the future. Making it a 'required' call pretty much undermines the *entire point* of a managed environment given that it forces strong ownership.

The unfortunate reality is that there is enormous utility in the 'using' keyword because it allows for 'nice and easy' C# language integration. That is the "guaranteed call when this thing is about to go out of scope". Unfortunately the 'using' keyword calls on the IDisposable interface, making it pretty useless if you wanted to call 'close' (without breaking the IDisposable interface).

Because of the confusion surrounding IDisposable and its poor implementation in the component model, IDisposable is pretty much a void contract, meaning you can't really rely on it meaning anything, which means you need to consider how you are going to treat it on a case by case basis (i.e. *per implementation*, there are no saving graces with regards to forward compatibility, and if we're lucky we'll see that interface deprecated in future releases in favor of a broader and better defined set of interfaces, such as IResource, IScoped, with compiler support, etc.)

There are a host of other issues around IDisposable too. It's a shame there isn't a separate interface for the 'using' keyword to target. It's a shame that resource management is still so poor. .NET doesn't give you 'resource management'. It gives you a shoddy 'strong ownership component model'. It gives you 'memory management' but only for the bits that it calls 'managed memory' and you can still undermine it entirely by holding on to a managed reference. If you think you got much more than a standardised type system, nicer API, a VM and a pretty language (that looks exactly the same as Java) with .NET, then you thought wrong. Memory management is still your problem.

John.

p.s. foreach, for, do, params, etc. all have very tightly defined, logical and well understood behavior. IDisposable doesn't.


Copyright © 2003-2005 John Elliot