Eilidh
Eilidh

Reputation: 1298

using as a syntactic convenience for Dispose on a Stream

I'm a little confused. I've been spending time looking into a variety of topics to ensure my code is robust, including IDisposable and its very own syntactic sugar of the using statement to ensure unmanaged resources are released.

As I understand it, using is translated by the compiler into a try-finally block with the object in the try block and the call to Dispose in the finally block.


As per my understanding, this would make the following two pieces of my code functionally equivalent -

using

public void LoadFile(string filePath)
{
    BinaryFormatter formatter = new BinaryFormatter(); 

    if (File.Exists(filePath)) 
    { 
        using (Stream input = File.OpenRead(filePath))
        { 
            // ... 
        }
    } 
}

Dispose

public void LoadFile(string filePath)
{
    BinaryFormatter formatter = new BinaryFormatter(); 

    if (File.Exists(filePath)) 
    { 
        try
        {
            Stream input = File.OpenRead(filePath);
        }
        finally 
        {
            input.Dispose(); 
        }
    } 
}    

This is where I'm confused. In the first example, using using, I'm not sure how I can put in my own exception handler when it is structured this way, as the underlying try-finally is obfuscated.

In the second example, using Dispose, I get the compiler error "The name input does not exist in this context".

Obviously I'm not understanding this fully... Any help would be much appreciated :)

Upvotes: 0

Views: 82

Answers (2)

Matthew Watson
Matthew Watson

Reputation: 109712

Using using doesn't prevent you from adding whatever exception handling you need:

public void LoadFile(string filePath)
{
    BinaryFormatter formatter = new BinaryFormatter(); 

    if (File.Exists(filePath)) 
    { 
        using (Stream input = File.OpenRead(filePath))
        { 
            try
            {
                // Whatever
            }

            catch (Exception exception)
            {
                // Do something with exception -
                // could log and suppress, or rethrow,
                // or whatever you need.
            }
        }
    } 
}

or

public void LoadFile(string filePath)
{
    BinaryFormatter formatter = new BinaryFormatter(); 

    if (File.Exists(filePath)) 
    { 
        try
        {
            using (Stream input = File.OpenRead(filePath))
            { 
                // Whatever
            }
        }

        catch (Exception exception)
        {
            // Do something with exception -
            // could log and suppress, or rethrow,
            // or whatever you need.
        }
    } 
}

It just ensures that no matter what*, the file will be closed.

*barring something nasty like Environment.FailFast()

Upvotes: 1

Selman Genç
Selman Genç

Reputation: 101701

You need to declare your variable outside of the try block so it will be accessible from catch and finally blocks:

if (File.Exists(filePath)) 
{ 
    Stream input = null;
    try
    {
       input = File.OpenRead(filePath);
    }
    finally 
    {
        if(input != null)
           input.Dispose(); 
    }
} 

Upvotes: 0

Related Questions