Code Trivia #7

Lets go for another code trivia, it’s business as usual, you just need to find what’s wrong with the following code:

static void Main(string[] args)
{
    using (var file = new FileStream("test", FileMode.Create) { WriteTimeout = 1 })
    {
        file.WriteByte(0);
    }
}

TIP: There's something very wrong with this specific code and there's also another subtle problem that arises due to how the code is structured.


As explained in the comments, the using statement expands to the following code leading to the FileStream object never getting disposed because the finally is never executed.

FileStream file = new FileStream("test", FileMode.Create) { WriteTimeout = 1 };
try
{
    file.WriteByte(0);
}
finally
{
    if (file != null)
        ((IDisposable)file).Dispose();
}

With this in mind, one could be tempted to use a custom try/finally block for handling this situation. Something like this:

FileStream file = null;
try
{
    file = new FileStream("test", FileMode.Create)
    {
        WriteTimeout = 1
    };

    file.WriteByte(0);
}
finally
{
    if (file != null)
        file.Dispose();
}

However this suffers from the same problem but due to a different cause. Even though the constructor for the object is called inside the try clause the object initializer syntax prevents it from being assigned to the file variable before all properties have been initialized, leading to the file stream still not being disposed.

The expansion caused by the object initializer syntax is shown in the next sample of code:

FileStream file = null;
try
{
    FileStream compilerGenerated = new FileStream("test", FileMode.Create);

    compilerGenerated.WriteTimeout = 1;

    file = compilerGenerated;

    file.WriteByte(0);
}
finally
{
    if (file != null)
        file.Dispose();
}

Basically, you need to be careful with using blocks where the resource initialization expression may throw an exception and you also need to pay careful attention on the subtleties of using object initializer syntax.

About these ads
Leave a comment

4 Comments

  1. No idea… :-/

    Reply
  2. Jorge Ferreira

     /  December 5, 2011

    FileStream.CanTimeout returns false which means WriteTimeout setter will throw InvalidOperationException.

    Reply
  3. Jorge Ferreira

     /  December 5, 2011

    But, more importantly, the FileStream will not be disposed because, due to the InvalidOperationException being thrown in the WriteTimeout setter, it will never be assigned to the file variable on the using block. This is the nature how the using block is translated into a try…finally.

    Reply
  4. João Angelo

     /  December 6, 2011

    Yep, correct on both, post updated.

    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

Follow

Get every new post delivered to your Inbox.

Join 27 other followers