Is using ‘using’ block really helpful?

Introduction and Background

So, it all began on the Facebook when I was posting a status (using Twitter) about a statement that I was feeling very bad that .NET team had left out the “Close” function while designing their .NET Core framework. At first I thought maybe everything was “managed” underground until I came up to an exception telling me that the file was already being used. The code that I was using was something like this,

if(!File.Exists("path")) { File.Create("path").Close(); }

However, “Close” was not defined and I double checked against .NET Core reference documentations too, and they suggested that this was not available in .NET Core framework. So I had to use other end… Long story short, it all went up like this,

I am unable to understand why was “Close” function removed from FileStream. It can be handy guys, @dotnet.

Then, Vincent came up with the idea of saying that “Close” was removed so that we all can use “using” blocks, which are much better in many cases.

You don’t need that. It’s handier if you just put any resource that eats resources within the “using block”. 🙂

Me:

How does using, “using (var obj = File.Create()) { }” make the code handier?

I was talking about this, “File.Create().Close();”

Now, instead of this, we have to flush the stream, or perform a flush etc. But I really do love the “using block” suggestion, I try to use it as much as I can. Sometimes, that doesn’t play fair. 😉

He:

Handier because I don’t have to explicitly call out the “Close()” function. Depends on the developer’s preference, but to me, I find “using (var obj = File.Create()) { }” handier and sexier to look at rather than the plain and flat “File.Create().Close();”. Also, it’s a best practice to “always” use the using block when dealing with objects that implements IDisposable to ensure that objects are properly closed and disposed when you’re done with it. 😉

As soon as you leave the using block’s scope, the stream is closed and disposed. The using block calls the Close() function under the hood, and the Close() calls the Flush(), so you should not need to call it manually.

Me:

I will go with LINQPad to see which one is better. Will let you know.

So, now I am here, and I am going to share what I find in the LINQPad. The fact is that I have always had faith in the code that works fast and provides a better performance. He is an ASP.NET MVP on Microsoft and can be forgiven for the fact that web developers are trained on multi-core CPUs and multi-deca-giga-bytes of RAMs so they use the code that looks cleaner but… He missed the C# bytecode factor here. I am going to use LINQPad to find out the underlying modifications that can be done to find out a few things.

Special thanks to Vincent: Since a few days I was out of topics to write on, Vincent you gave me one and I am going to write on top of that debate that we had.

Notice: I also prefer using the “using” block in almost every case. Looks handier, but the following code block doesn’t look handier at all,

using (var obj = File.Create("path")) { }

And this is how it began…

Exploring the “using” and simple “Close” calls

LINQPad is a great software to try out the C# (or .NET framework) code and see how it works natively, it lets you see the native bytecode of ,NET framework and also lets you perform and check the tree diagrams of the code. The two types that we are interested in are, “using” statement of .NET framework and the simple “Close” calls that are made to the objects to close their streams.

I used a Stopwatch object to calculate the time taken by the program to execute each task, then I match the results of each of the program with each other to find out which one went fast. Looking at the code of them both, it looks the thousand-feet high view of them both looks the same,

// The using block
using (var obj = File.Create("path")) { }

// The clock method
File.Create("path").Close();

They both the same, however, their intermediate code shows something else.

// IL Code for "using" block
IL_0000: nop 
IL_0001: ldstr "F:/File.txt"
IL_0006: call System.IO.File.Create
IL_000B: stloc.0 // obj
IL_000C: nop 
IL_000D: nop 
IL_000E: leave.s IL_001B
IL_0010: ldloc.0 // obj
IL_0011: brfalse.s IL_001A
IL_0013: ldloc.0 // obj
IL_0014: callvirt System.IDisposable.Dispose
IL_0019: nop 
IL_001A: endfinally 
IL_001B: ret 

// IL Code for the close function
IL_0000: nop 
IL_0001: ldstr "F:/File.txt"
IL_0006: call System.IO.File.Create
IL_000B: callvirt System.IO.Stream.Close
IL_0010: nop 
IL_0011: ret

Oh-my-might-no! There is no way, “using” block could have ever won with all of that extra intermediate code for the .NET VM to execute before exiting. The time taken by these commands was also tested and for that I used the native Stopwatch object to calculate the “ticks” used, instead of the time in milliseconds by each of the call. So my code in the LINQPad looked like this,

void Main()
{
   Stopwatch watch = new Stopwatch();
   watch.Start();
   using (var obj = File.Create("F:/file.txt")) { }
   watch.Stop();
   Console.WriteLine($"Time required for 'using' was {watch.ElapsedTicks}.");
 
   watch.Reset();
   watch.Start();
   File.Create("F:/file.txt").Close();
   watch.Stop();
   Console.WriteLine($"Time required for 'close' was {watch.ElapsedTicks}.");
}

The execution of the above program always results in a win for the “Close” function call. In sometimes it was a close result, but still “Close” function had a win over the “using” statement. The results are shown the images below,

screenshot-5120 screenshot-5121 screenshot-5122

The same executed, produced different results, there are many factors to this and it can be forgiven for all of them,

  1. Operating system might put a break to the program for its own processing.
  2. Program might not be ready for processing.
  3. Etc. etc. etc.

There are many reasons. For example, have a look at the last image, the time taken was 609 ticks. Which also includes the ticks taken by other programs. The stopwatch was running ever since, and that is what caused the stopwatch to keep tracking the ticks. But in any case, “using” statement was not a better solution from a low level code side.

Final words

Although I also recommend using the “using” block statement in C# programs, but there is a condition where you should consider using one over other. For example, in this condition, we see that implementing one over the other has no benefit at all, but just a matter of personal interest and like. Although I totally agree to Vincent where he mentions that “using” block is helpful, but in other cases. In this case, adding a Close call is a cleaner (IMO) way of writing the program as compared to the other one.

At the end, it is all in the hands of the writer… Select the one you prefer.

Advertisements

One thought on “Is using ‘using’ block really helpful?

  1. gregsdennis

    I agree that Close() is important. I can think of plenty of asynchronous scenarios where you open a file in one place and course it somewhere else. Or maybe you want to keep an OS-level lock on the file… Removing that method was a mistake.

    Like

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s