Alex Rivera | Logout

How do you catch exceptions with "using" in C#

Asked 2009-02-05T22:34:24.697
42

Given this code:

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
}

I'm used to writing try/catch/finally blocks for my data access, however, I'm being exposed to "using" which seems like a much simpler method of doing this. However, I'm trying to figure out how to catch exceptions that may occur.

Could you please give me an example of how you'd catch exceptions?

Edited to add:

I'm being led to believe that "using" is a replacement for my try/catch/finally blocks. I understand that using doesn't catch exceptions. So how is this a replacement?

Edit
Report

1 Answer

18

This...

using (var cmd = new SqlCommand("SELECT * FROM Customers"))
{
    cmd.CommandTimeout = 60000;
    ...
}

...is almost semantically-identical (i.e. syntactical-sugar) for this:

{
    SqlCommand cmd = new SqlCommand("SELECT * FROM Customers");
    try
    {
        cmd.CommandTimeout = 60000;
        ...
    }
    finally
    {
        if (cmd is IDisposable disposable)
        {
            disposable.Dispose();
        }
    }
}

Note that:

  • The cmd local cannot be reassigned, this is one of the few cases where C# has "readonly locals" (along with foreach).
  • The outer braces ({ and }) define an anonymous scope (also known as a compound statement or just a "block") which limits the lexical scope of cmd so it cannot be referenced by name after it has been disposed (but you can still alias it if you really wanted to).
  • While the compiler will perform the "is-IDisposable" check at compile-time (otherwise the usingstatement will not compile), a hidden implicit conversion toIDisposable is necessary in case the subject (cmd) only _explicitly_ implements IDisposableinstead of via a publicvoid Dispose()` method.

So when people are telling you that "using" is a replacement for try/catch/finally they are implying that you should use the long-hand form but add in your catch block:

var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
    cmd.CommandTimeout = 60000;
    ...
}
catch (Exception ex)
{
    ...//your stuff here
}
finally
{
    if (cmd != null)
        cmd.Dispose();
}
answered 2009-02-05T22:57:09.937

Your Answer