using () 문에서 반환하면 부작용이 있습니까?


125

의 메소드 값 반환 내부 의 DataContext를 가져옵니다 using 문은 항상 일 것 같습니다 같은 :

public static Transaction GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        var transaction = (from t in db.Transactions
                              orderby t.WhenCreated descending
                              where t.Id == singleId
                              select t).SingleOrDefault();
        return transaction;
    }
}

그러나 항상 사용 대괄호를 벗어나기 전에 무언가닫아야 한다고 생각합니다 . 예를 들어 using 문 전에 트랜잭션을 정의 하고 대괄호 내부 에서 값 얻은 다음 대괄호 뒤에 반환 합니다.

사용 괄호 밖에서 변수를 정의하고 리턴하는 것이 더 나은 방법이거나 자원을 보존 하는가?


1
이것의 변형에 대해서는 일반적인 IL을 보는 것이 흥미로울 수 있습니다. 생성 된 IL에는 거의 차이가 없을 것으로 생각됩니다. 나는 일반적으로 var 트랜잭션을 선언하지 않아도 표현식의 결과를 반환합니다.
Jonesie

답변:


164

아니, 나는 이것이 더 분명하다고 생각한다. 걱정하지 마십시오. Dispose여전히 "나갈 때"라고 부릅니다 . 반환 값이 완전히 평가 된 후에 만 가능 합니다. 언제라도 예외가 발생하더라도 (반환 값 평가 포함) Dispose여전히 호출됩니다.

확실히 더 긴 경로를 취할 는 있지만 (정신적으로) 추적하기 위해 부스러기와 추가 컨텍스트를 추가하는 두 개의 추가 라인입니다. 실제로 추가 로컬 변수는 필요하지 않지만 디버깅 측면에서 편리 할 수 ​​있습니다. 당신 단지 가질 있습니다 :

public static Transaction GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        return (from t in db.Transactions
                orderby t.WhenCreated descending
                where t.Id == singleId
                select t).SingleOrDefault();
    }
}

사실, 난 점 표기법을 사용하고 넣어 유혹 될 수 Where내에서 조건을 SingleOrDefault:

public static Transaction GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        return db.Transactions.OrderByDescending(t => t.WhenCreated)
                              .SingleOrDefault(t => t.Id == singleId);
    }
}

2
Sine 그것은 당신입니다 @ jon, using 블록 내에서 예외가 발생하더라도 여전히 안전합니까?
Dave Archer

6
예. try / finally 구성을 위해 단순히 구문 설탕을 사용하는 것
Mitch Wheat

@David : Mitch가 말했듯이 괜찮습니다. 대답을 더 명확하게하기 위해 업데이트했습니다 :)
Jon Skeet

2
왜 OrderByDescending을 SingleOrDefault와 함께 사용합니까?
erikkallen

2
@ erikkallen : LINQ에는 불행히도 "MaxBy"가 없으므로 최대 값으로 행을 얻을 수 없습니다. LINQ to Objects의 경우 상당히 쉽게 자신의 글을 작성할 수 있지만이 경우 더 나은 방법을 모르겠습니다. 대신 무엇을 제안 하시겠습니까?
Jon Skeet

32

이것 좀 봐

C #의 'using'문 이해

CLR은 코드를 MSIL로 변환합니다. using 문은 try 및 finally 블록으로 변환됩니다. 이것이 using 문이 IL에서 표현되는 방식입니다. using 문은 획득, 사용 및 폐기의 세 부분으로 번역됩니다. 자원을 먼저 확보 한 후 사용법은 finally 절과 함께 try 문으로 묶습니다. 그런 다음 객체는 finally 절에 배치됩니다.


4
흥미로운 통찰력. 감사.
Kangkan

1
그것은 질문으로 변환됩니다. try-finally의 try-block에서 돌아온 부작용은 무엇입니까?
Henk Holterman

3
아니요, 마지막으로 항상 호출됩니다. techinterviews.com/interview-questions-for-c-developers
Adriaan Stander

6

명세서 내부에서 돌아 오는 부작용 은 없습니다using() .

가장 읽기 쉬운 코드인지 여부는 또 다른 토론입니다.


0

내 생각 엔 다 똑같아 코드에는 나쁘지 않습니다. .NET 프레임 워크는 객체가 생성 된 위치를 신경 쓰지 않습니다. 중요한 것은 참조 여부입니다.


-1

예, 부작용이있을 수 있습니다. 예를 들어 ASP.NET MVC 작업 메서드에서 동일한 기술을 사용하면 "ObjectContext 인스턴스가 삭제되어 더 이상 연결이 필요한 작업에 사용할 수 없습니다"라는 오류가 발생합니다.

public ActionResult GetMostRecentTransaction(int singleId)
{
    using (var db = new DataClasses1DataContext())
    {
        var transaction = (from t in db.Transactions
                              orderby t.WhenCreated descending
                              where t.Id == singleId
                              select t).SingleOrDefault();
        return PartialView("_transactionPartial", transaction);
    }
}

2
using 문 외부에서 트랜잭션을 정의하면 동일한 오류가 발생합니다. 이 경우 키워드 사용은 관련이 없습니다.
Costa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.