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.

4 thoughts on “Code Trivia #7”

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

  2. 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.

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