Skip to content

the other thing about “using” blocks

C#’s using statement is well recognized for one thing: calling dispose on objects so that you don’t have to. That bit is wonderful:

string contents;
using (var f = File.OpenText("/path/to/file") {
	contents = f.ReadToEnd();
}

This is much simpler than the fully spelled out alternative:

string contents;
var f = File.OpenText("/path/to/file");
try {
	contents = f.ReadToEnd();
} finally {
	f.Dispose();
}

And even this longer form actually misses one of the more interesting aspects of the using statement…

string contents;
var f = File.OpenText("/path/to/file");
try {
	contents = f.ReadToEnd();
} finally {
	f.Dispose();
}
f.ReadToEnd(); // oops! ObjectDisposedException at runtime
f = null; // you could set it to null
f.ReadToEnd(); // but now you have a NullReferenceException, even more mysterious

The using statement on the other hand, creates a scope, so its variable can’t be referenced at all after it is disposed:

string contents;
using (var f = File.OpenText("/path/ro/file") {
	contents = f.ReadToEnd();
}
f.ReadToEnd(); // unknown identifier error at compile-time

An entirely equivalent bit of code can be written, using an anonymous scope, but it starts to look quite baroque:

string contents;
{
	var f = File.OpenText("/path/ro/file");
	try {
		contents = f.ReadToEnd();
	} finally {
		f.Dispose();
	}
}
f.ReadToEnd(); // Unknown identifier at compile-time again, but 2x the lines and 2x the scopes!

using provides the try-finally-dispose structure, and also provides a scope. The scope means a whole class of errors where resources are accessed after being released is transformed from run-time to compile-time errors. Dealing with errors at compile-time is quicker, and with the right tools to highlight problems, the compile problems can be seen directly in the code as it is being edited.

Categories: blocks, c#, compiler, dispose, lean on the compiler, object instantiation, resource acquisition, scope, using.

Tags: , , , , , ,

Comment Feed

3 Responses

  1. good point.

  2. Or you can just enclose the variable declaration and usage in a pair of curly brases (also works for non-IDisposable variables):

    {
    var f = File.OpenText(“/path/ro/file”);
    contents = f.ReadToEnd();
    }
    f.ReadToEnd(); // Unknown identifier at compile time

    TeevusSeptember 1, 2011 @ 18:51
  3. @Teevus: You’re right. I try to speak to anonymous scopes in the very last example, but yes, they can be free standing as well. I wouldn’t want to use a “using” statement only to produce a scope, because an anonymous scope would do the same job more simply. Even when I am tempted to use an anonymous scope to limit some variable, I try to think up a good name for the scope and turn it in to a method.



Some HTML is OK

or, reply to this post via trackback.