using 문 내에서 예외가 throw되면 Dispose가 계속 호출됩니까?


103

아래 예에서 연결이 using문 내에있는 경우 예외가 throw되면 연결이 닫히고 삭제 됩니까?

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

아래의 코드가이를 확인한다는 것을 알고 있지만 using 문이 어떻게 작동하는지 궁금합니다.

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 연결이 닫히도록하는 적절한 방법은 무엇입니까?

답변:


112

예, 부분이 존재하는 경우 호출 할 usingtry / finally 블록에 코드를 래핑 합니다. 그러나 구현중인 인터페이스와 그에 따른 메서드 만 확인하므로 직접 호출하지 않습니다 .finallyDispose()Close()IDisposableDispose()

또한보십시오:


5
연결 클래스에 대해 지적하기 위해 Dispose ()가 실제로 내부적으로 Close ()를 호출하는 것을 볼 수 있습니다. 상태라면 할 수 있습니다.
Chris Marisic

2
당신이 맞습니다. 그러나 나는 이것이 IDisposable 또는 관련 패턴과 관련이 있다고 생각하도록 누군가를 오도하고 싶지 않았기 때문에 의도적으로 언급하지 않았습니다. 이 특정 구현이 Close ()를 호출한다는 사실은 패턴이 아니라 구현의 세부 사항입니다.
Jeff Yates

3
MSDN using documentation 은 또한이 대답을 확인합니다 . using 문은 개체에서 메서드를 호출하는 동안 예외가 발생하더라도 Dispose가 호출되도록합니다. 개체를 try 블록에 넣은 다음 finally 블록에서 Dispose를 호출하여 동일한 결과를 얻을 수 있습니다. 사실, 컴파일러가 using 문을 번역하는 방법입니다.
브로드밴드

20

리플렉터가 코드에 의해 생성 된 IL을 디코딩하는 방법은 다음과 같습니다.

private static void Main (string [] args)
{
    SqlConnection conn = new SqlConnection ( "...");
    시험
    {
        conn.Open ();
        DoStuff ();
    }
    드디어
    {
        if (conn! = null)
        {
            conn.Dispose ();
        }
    }
}

그래서 대답은 '예'입니다.

DoStuff ()
예외가 발생합니다.


conn.Open ()에서 예외가 발생하면 추가합니다. : D
Jeff Yates

네 물론입니다. using 절이 예외를 throw 한 후 블록에있는 것이 있으면 연결이 닫힙니다. finally 블록이 실행되지 않는 유일한 방법은 "new SqlConnection (...)"이 발생하는 경우이지만이 경우 실제로 닫을 유효한 열린 연결이 없을 것입니다. 그래서 괜찮습니다.
Florin Sabau

-1

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

이것은 OP 질문에 대답합니까 ??
Joey Phillips

예. 내 대답은 아니오 야. Dispose ()는 첨부 된 코드에서 호출되지 않습니다. 또한 throw되는 예외가 처리되지 않고 프로그램이 종료됩니다.
Chad

잘못된 파일을보고있는 것 같습니다. "Dispose ()"가 임시 파일에 기록됩니다. 아무도 using-block이 예외를 처리 할 것이라고 주장하지 않습니다. 디버거없이 이것을 실행 해보십시오.
LarsTech

이 똑같은 코드를 실행하고 Dispose ()를 호출합니다. 당신의 대답이 맞습니까?
Dnomyar96
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.