Вызывается ли Dispose все еще, когда исключение выбрасывается внутри оператора using?

В приведенном ниже примере соединение закрывается и удаляется, когда генерируется исключение, если оно находится в инструкции using?

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

Я знаю, что этот код ниже будет убедиться, что это так, но мне любопытно, как это делает оператор.

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

Связано:

Каков правильный способ обеспечения соединения SQL закрывается при вызове исключения?

Ответ 1

Да, using обертывает ваш код в блок try/finally, где часть finally вызывает Dispose(), если она существует. Однако он не будет называть Close() напрямую, поскольку он проверяет только реализованный интерфейс IDisposable и, следовательно, метод Dispose().

См. также:

Ответ 2

Так рефлектор декодирует IL, сгенерированный вашим кодом:

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

Итак, ответ да, он закроет соединение, если

DoStuff()
выдает исключение.

Ответ 3

Dispose() не вызывается в этом коде.

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