How do you catch exceptions with “using” in C#

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?

using isn’t designed to catch exceptions; it’s designed to give you an easy way to wrap a try/finally around an object that needs to be disposed. If you need to catch and handle exceptions then you’ll need to expand it into a full try/catch/finally or put a containing try/catch around the whole thing.


To answer your edit (is using a replacement for try/catch/finally?) then no, it isn’t. Most of the time when using a disposable resource you aren’t going to handle the exception there and then because there’s normally nothing useful you can do. So it provides a convenient way to just ensure that the resource is cleaned up irrespective of what you’re trying to do works or not.

Typically code that deals with disposable resources is working at too low a level to decide what the correct action is on failure, so the exception is left to propagate to the caller who can decide what action to take (e.g. retry, fail, log, etc.).
The only place where you’d tend to use a catch block with a disposable resource is if you’re going to translate the exception (which is, I assume, what your data access layer is doing).

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();
}

Wrap all the using statements into a try/catch. Like everyone else has said, using is for cleaning up classes that implement the IDisposable interface

try
{

 using (var conn = new SqlConnection("..."))
 {
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
 }
}
catch(Exception ex)
{
//Handle, log, rethrow exception
}

If you want to catch exceptions there you probably should go back to using try/catch/finally. Just put the .Dispose() calls in the finally block.

Using statements have nothing to do with Exceptions. Using blocks just insure that Dispose is called on the object in the using block, when it exits that block. I.E:

using(SqlConnection conn = new SqlConnection(conStr))
{
   //use conn
}//Dispose is called here on conn.

If opening the connection raises an exception (or anything else in that block for that matter) it will still bubble to the top and will be like any other unhanded exception.

You can still catch (or ignore) exceptions exactly as you would have previously. The point is that you no longer need to worry about disposing of the database connection.

ie, If your application requires that you trap exceptions for some other reason (eg, logging) then go ahead, but you no longer need to do so if you only want to dispose of the database connection:

using (SqlConnection conn = new SqlConnection(...))
{
    // do your db work here
    // whatever happens the connection will be safely disposed
}

If you want to catch the exception for some other reason, you can still do so:

try
{
    using (SqlConnection conn = new SqlConnection(...))
    {
        // do your db work here
        // whatever happens the connection will be safely disposed
    }
}
catch (Exception ex)
{
    // do your stuff here (eg, logging)
    // nb: the connection will already have been disposed at this point
}
finally
{
    // if you need it
}

Put into a try catch block the using block/s. Their implicit finally statements devoted to their objects disposition will be executed before the outer block catch statement and its content.

Leave a Comment