121

In the example below, is the connection going to close and disposed when an exception is thrown if it is within a using statement?

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    // stuff happens here and exception is thrown...
}

I know this code below will make sure that it does, but I'm curious how using statement does it.

var conn;
try
{
    conn = new SqlConnection("...");
    conn.Open();
    // stuff happens here and exception is thrown...
}
// catch it or let it bubble up
finally
{
    conn.Dispose();
}

Related:

What is the proper way to ensure a SQL connection is closed when an exception is thrown?
Community
  • 1
  • 1
Brian Kim
  • 24,916
  • 6
  • 38
  • 26

3 Answers3

130

Yes, using wraps your code in a try/finally block where the finally portion will call Dispose() if it exists. It won't, however, call Close() directly as it only checks for the IDisposable interface being implemented and hence the Dispose() method.

See also:

Community
  • 1
  • 1
Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
  • 7
    Just to point out on the connection classes if you reflector over them you will see Dispose() does indeed internally call Close(). If it's in a state it can. – Chris Marisic Feb 06 '09 at 14:37
  • 3
    You are correct, it does. However, I deliberately didn't mention it as I didn't want to mislead anyone to think this has anything to do with IDisposable or the associated pattern. The fact that this particular implementation calls Close() is a detail of the implementation, not the pattern. – Jeff Yates Feb 06 '09 at 22:01
  • 3
    [MSDN using documentation](http://msdn.microsoft.com/en-us/library/yh598w02.aspx) also confirms this answer: _The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler._ – broadband May 22 '14 at 08:00
21

This is how reflector decodes the IL generated by your code:

private static void Main(string[] args)
{
    SqlConnection conn = new SqlConnection("...");
    try
    {
        conn.Open();
        DoStuff();
    }
    finally
    {
        if (conn != null)
        {
            conn.Dispose();
        }
    }
}

So the answer is yes, it will close the connection if

DoStuff()
throws an exception.
Florin Sabau
  • 1,065
  • 8
  • 18
  • Add if conn.Open() throws an exception. :D – Jeff Yates Feb 05 '09 at 23:07
  • Yeah sure. If whatever is in the block AFTER the using clause throws an exception, the connection will be closed. The only way the finally block won't be executed is if the "new SqlConnection(...)" throws, but in that case you wouldn't have actually a valid open connection to close. So it's fine. – Florin Sabau Feb 05 '09 at 23:15
-1

Dispose() doesn't get called in this code.

class Program {
    static void Main(string[] args) {
        using (SomeClass sc = new SomeClass())
        {
            string str = sc.DoSomething();
            sc.BlowUp();
        }
    }
}

public class SomeClass : IDisposable {
    private System.IO.StreamWriter wtr = null;

    public SomeClass() {
        string path = System.IO.Path.GetTempFileName();
        this.wtr = new System.IO.StreamWriter(path);
        this.wtr.WriteLine("SomeClass()");
    }

    public void BlowUp() {
        this.wtr.WriteLine("BlowUp()");
        throw new Exception("An exception was thrown.");
    }

    public string DoSomething() {
        this.wtr.WriteLine("DoSomething()");
        return "Did something.";
    }

    public void Dispose() {
        this.wtr.WriteLine("Dispose()");
        this.wtr.Dispose();
    }
}
Chad
  • 17
  • 1
  • Does this answer the OP question?? – Joey Phillips May 08 '19 at 16:36
  • 1
    Yes. The answer is no. Dispose() does not get called in the attached code. Further more the exception that is thrown is not handled and the program blows up. – Chad May 09 '19 at 18:36
  • You must be looking at the wrong file. "Dispose()" gets written to your temp file. Nobody claims a using-block will handle an exception. Try running this without a debugger. – LarsTech May 09 '19 at 19:00
  • I ran this exact same code and it does call Dispose(). Are you sure your answer is correct? – Dnomyar96 Jun 03 '20 at 06:12
  • @LarsTech, why running without a debugger invokes dispose? With debugging it is not even called – Farhad Mammadli Aug 02 '22 at 10:11