A few days ago, Benjamin pointed me to a feature in C#, I was not aware of, yet. You can stack using statements. In the following I will show an example where this might come in very handy.
I recently worked on a project where we had to process large text files (with large I mean 14GB each). In a pre-processing step we cleaned up the files, processed each line, validated it against a set of rules and then either wrote it back to a output file or a temporary which required further processing steps. Due to the complexity of the validation we decided to go with a small C# program that does the job.
A fast and convenient way was utilizing a set of StreamReaders and StreamWriters and applying using statements a to read and write the files. As Anoop pointed out, not using usings is one of a common mistakes .NET developers should avoid. Eventually, the code looked similar to the following example by cascading the using statements.
using (StreamReader reader = new StreamReader(@"c:input.txt")) { using (StreamWriter successWriter = new StreamWriter(@"c:success.txt")) { using (StreamWriter failWriter = new StreamWriter(@"c:fail.txt")) { // all the magic happens here } } }
That would be the way many developers would write the code, and if you have a look at the MSDN documentation about using statements this seems to be the way to do it. But the C# 4.0 Language Specification does give you an hint that there is more you could do.
For a using statement stmt of the form:
using ( resource-acquisition ) embedded-statement
The definite assignment state of v at the beginning of resource-acquisition is the same as the state of v at the beginning of stmt.
The definite assignment state of v on the control flow transfer to embedded-statement is the same as the state of v at the end of resource-acquisition.
What’s not obvious here, is the fact that you can stack using statements utilizing one code block. In this case you embedded-statement is another using statement. In fact that’s not different how most of us use cascading for and foreach loops. In fact, this is not a new feature of C# but something you might not have considered before.
using (StreamReader reader = new StreamReader(@"c:input.txt")) using (StreamWriter successWriter = new StreamWriter(@"c:success.txt")) using (StreamWriter failWriter = new StreamWriter(@"c:fail.txt")) { // all the magic happens here }
Writing the code like this reduces a lot of noise and indentation in your code, keeps the resource acquisition tight and might be definitely worth keeping in mind.