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.
good point.
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
@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.