What’s the deal with the C# “using” construct?

We spent a little bit of time today talking about the “using” construct and potential problems and confusion that people have been having with it. For those who don’t know, the “using” statement is a simple C# construct that provides concise syntax for a very common pattern. Specifically, the C# language specification says that it will convert code with the following structure:

This allows you to concisely work with a resource that needs to be disposed in a timely fashion. A good example of this are things like file handles. There are a limited number that the OS can give out, and it’s quite possible to run out of them if you haphazardly request them and then depend on the garbage collector to clean them up for you. Now, in a perfect world, the GC would be aware of non-memory resources and it would reclaim things like handles when they were no longer being used by you. However, in today’s world that’s not how things work so the “using” construct can be used in conjunction with the IDisposable interface pattern to accomplish that.

Now, we could have not introduced the “using” construct, however without it code tends to get incredibly messy. Consider if you are using two disposable resources, the code then becomes:

(personally, I prefer the latter). That’s a heck of a lot more concise and far easier to grok.

So, what’s the problem that people have been having with the “using” construct? Well, as you may have already noticed there’s a potential problem whereby a resource you’ve acquired is not released in a timely manner. When can that happen? Well consider the following:

Uh-oh. We have a problem. You’ve acquired the resource in “expression”, but before entering the “try” some asynchronous exception occurs and so the resource is never disposed. At first glance it seems like there is a trivial fix for this. Simply change the code transformation so that it generates:

Terrific right? Now if an asynchronous exception occurs after “expression” is invoked, we’ll be inside the “try” and so the “finally” block will execute and clean up the resource for us. Unfortunately, that’s still not the case! How so? Well consider the following:

Sigh… The resource has been acquired, but when the “finally” runs “temp” will still be null, and nothing will get disposed at that time.

OMG! The sky is falling! The sky is falling!

Seems like you’re in a horrible position here right!? How on earth will you know if your resources are going to be cleaned up? Are we now in a world where you’re going to be leaking resources and you’re not going to be able to trust your managed code?

Fortunately, no, things are not as dire as they seem. Why? Well, first let’s start with an assumption. If you are writing code that follows the .Net guidelines, and you listen to tools like FxCop, then you’re going to be writing your classes that implement IDisposable as recommended in the MSDN documentation.

What this means is that even if you forget, or fail (because of an asynchronous exception), to explicitly call “Dispose” on the resource it will be ok because the GC will eventually finalize your object which will end up doing the same.

But wait a minute. Didn’t I just say that depending on the GC to clean up critical resources was a bad practice since you might run out of resources before the GC kicks in? Yes I did. However, the difference here is that if you have the bad luck to run into this asynchronous exception problem you stand the chance of not disposing at most a couple of disposable objects. And the chance of those few objects causing you to be unable to acquire any more resources is exceedingly slim. Contrast that with code that just does something like this:

while (true) {
AcquireResource();
}

In this case you’re going to be leaking tons and tons of resources and it will very quickly become a problem for you. In the asynchronous case you will be leaking a worst a couple of resources, and they will almost certainly be reclaimed before they could ever be a problem.

It should also be noted that these asynchronous exceptions occur in extremely bad situations (like a thread dying). And, in native code, it’s often extremely difficult to recover from this at all. The managed world allows you to have a good balance. When an error occurs you may leak a resource, but even so it will quickly be reclaimed soon afterwards.

So if you’ve ever seen the transformation done by the C# compiler and wondered why it did what it did, well now you know.

The one problem that I have for using "using" is the lack of support for transactions.

When code goes out of a using block, there is no way to know if it was from an abnormal termination (exception) or a normal exit. If this were known, the Dispose() call could perform a commit or rollback as needed.

The System.Transaction guys have a ITransaction interface that derives IDisposable and includes a Rollback method–or something like that. If "Using" were to recognize the ITransaction pattern then it could actually do the right thing, rather than assume abnormal termination is normal.

My factory produces DataAccessAdapter instances, for the type of db passed in. Great. Now, it throws an exception, because it can’t cast IDataAccessAdapter to IDisposable. Though, the object returned from Create is implementing IDisposable.

So, instead of using the interface, I have to use the base class, which implements IDataAccessAdapter and IDisposable. However, this isn’t obvious. I.o.w.: the compiler should already throw an error in the using line that ‘IDataAccessAdapter’ doesn’t derive from IDisposable and therefore can’t be used in a using expression.

You know what would be great? How about having a using statement that automatically thethers to the local scope like C++/CLI stack based declaration. This avoids having to have nested braces that requires another level of indentation. Here’s what I mean:

We use using heaps – as it _almost_ gives you a concept similar to anyonymous methods.

One thing that’s always annoyed me, and it’s more about exception handling than using, but we run up against it every day – there should be a way you can ask in a finally block "did an exception occur"

What really annoys me, and I’ve tried every weird thing I can think of, is I can’t do what I really want to do and say "a transaction is committed if an exception doesn’t occur". I really want to write:

using (AmbientTransaction.Called("Update Prices"))

{

…

}

And it really bothers me that (as far as I can tell) it can’t be done.

This is a problem we really want to solve in Orcas. I noted a couple possible solutions at the bottom of the article. I had a few other speculations, but after conversations w/ Chris Brumme, I realized most of them were crap and we’d never recommend people write their code that way (nevermind have C# spit the code).

will ensure that an async exception won’t get raised, since we hold off on processing them during finally block execution. We also don’t execute them while you’re in a CER, running some opaque unmanaged code, and a few other corner scenarios. But holding up an async abort is a pretty rude thing to do, especially if you intend to block inside of it.

Further, you could imagine a class like

static class ReliableFactory

{

public static void New<T>(out T created)

where T : new()

{

try {}

finally { created = new T(); }

}

}

which would enable you to write

ExpressionType temp = null;

try {

ReliableFactory.New<ExpressionType>(out temp);

/* similar to above, an async exception won’t prevent the out assignment to temp */

statement

} finally {

if (temp != null) {

((IDisposable)temp).Dispose();

}

}

But this is fairly hokey.

I really hope we solve this problem in Orcas. But there’s quite a bit to do with Dispose that needs a fixin’, too. 🙂