The C# using statement


I had a talk with a colleague today about the using statement. It had come up in a job interview and he was thinking about the using statement at the top of the file. If I were asked about using, I would probably answer “you mean try … finally with a Dispose”.

The following code is nearly identical, when taken from an IL standpoint:

Code sample 1:

private static void GetData(string connectionString)
{
    SqlConnection connection = new SqlConnection(connectionString);
    try
    {
        connection.Open();
    }
    finally
    {
        connection.Dispose();
    }
}

Code sample 2:

private static void GetData(string connectionString)
{
    using(SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
    }
}

Need proof?

When reverse engineering file 1 to C#, you end up with the following:

private static void GetData(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
}
}

Looks just like example 2.
And here is the IL produced when you run this through Reflector (black lines are the same in both files, blue lines are from file 1 and red lines are from file 2):

.method private hidebysig static void GetData(string connectionString) cil managed
{
    .maxstack 2
    .locals init (
        [0] class [System.Data]System.Data.SqlClient.SqlConnection connection)

    .locals init (
        [0] class [System.Data]System.Data.SqlClient.SqlConnection connection,
        [1] bool CS$4$0000)

    L_0000: nop
    L_0001: ldarg.0
    L_0002: newobj instance void [System.Data]System.Data.SqlClient.SqlConnection::.ctor(string)
    L_0007: stloc.0
    L_0008: nop
    L_0009: ldloc.0
    L_000a: callvirt instance void [System.Data]System.Data.Common.DbConnection::Open()
    L_000f: nop
    L_0010: nop
    L_0011: leave.s L_001d
    L_0011: leave.s L_0023
    L_0013: nop

EXTRA LINES:
   
L_0014: ldnull
    L_0015: ceq
    L_0017: stloc.1
    L_0018: ldloc.1
    L_0019: brtrue.s L_0022

    L_0014: ldloc.0
    L_0015: callvirt instance void [System]System.ComponentModel.Component::Dispose()
    L_001a: nop
    L_001b: nop – MISSING FROM FILE WITH USING STATEMENT
    L_001c: endfinally
    L_001d: nop
    L_001e: ret
    .try L_0008 to L_0013 finally handler L_0013 to L_001d
    .try L_0008 to L_0013 finally handler L_0013 to L_0023
}

When do you use using and when do you use a try?

  • If there is ever a chance of having a catch added, use a try instead of using
  • If not, the choice is yours, but the using statement requires less typing.

Peace and Grace,
Greg

Twitter: @gbworld

Advertisements

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

%d bloggers like this: