2010-08-18 5 views
18

를 생성합니다. CreateReCaptcha (이 HtmlHelper, 문자열, 문자열) '개체'<> g__initLocal0 '은 모든 예외 경로를 따라 배치되지 않습니다. 모든 참조가 범위를 벗어나기 전에 System.IDisposable.Dispose 객체 '<> g__initLocal0'을 호출하십시오. 내가 개체 이니셜 라이저를 사용하지 않는 경우개체 이니셜 코드 분석 경고 CA2000

 

    using (var control = new ReCaptchaControl() 
    { 
     ID = id, 
     Theme = theme, 
     SkipRecaptcha = false 
    }) 
    { 
     // Do something here 
    } 
 

, 코드 분석은 행복하다 :

 

    using (var control = new ReCaptchaControl()) 
    { 
     control.ID = id; 
     control.Theme = theme; 
     control.SkipRecaptcha = false; 

     // Do something here 
    } 
 

두 코드 블록의 차이점은 무엇입니까 여기

코드인가? 나는 그들이 같은 일리노이가 될 것이라고 생각했다. 아니면 코드 분석 엔진의 버그입니까?

답변

31

아니요, 차이가 있습니다.

개체 이니셜 라이저는 모든 속성이 설정된 후에 변수 만 할당합니다.

Foo tmp = new Foo(); 
tmp.Bar = "Baz"; 
Foo x = tmp; 

속성 족 중 하나가 경우에 예외를 던진 경우, 오브젝트가 배치 될 것이라는 것을 의미한다 : 즉,이 님

Foo x = new Foo { Bar = "Baz" }; 

는 동일하다.

편집 : 내가 생각 ...이 시도 :

using System; 

public class ThrowingDisposable : IDisposable 
{ 
    public string Name { get; set; } 

    public string Bang { set { throw new Exception(); } } 

    public ThrowingDisposable() 
    { 
     Console.WriteLine("Creating"); 
    } 

    public void Dispose() 
    { 
     Console.WriteLine("Disposing {0}", Name); 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     PropertiesInUsingBlock(); 
     WithObjectInitializer(); 
    } 

    static void PropertiesInUsingBlock() 
    { 
     try 
     { 
      using (var x = new ThrowingDisposable()) 
      { 
       x.Name = "In using block"; 
       x.Bang = "Ouch"; 
      } 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Caught exception"); 
     } 
    } 

    static void WithObjectInitializer() 
    { 
     try 
     { 
      using (var x = new ThrowingDisposable 
      { 
       Name = "Object initializer", 
       Bang = "Ouch" 
      }) 
      { 
       // Nothing 
      } 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Caught exception"); 
     } 
    } 
} 

출력 : 더 "폐기 개체 초기화"라인이 없다 방법

Creating 
Disposing In using block 
Caught exception 
Creating 
Caught exception 

참고.

+1

이제 글을 쓰는 것이 맞습니다. IMO 이것은 쉽게 간과되는 함정입니다. 운좋게도 Visual Studio는 나보다 현명합니다. – Tero

+1

@ 존 - 그렇다면 'IDisposable을 구현하는 유형으로 객체 이니셜 라이저 구문을 사용하지 마십시오'라고 결론 지어도됩니다. (확장이 CA 엔진에 의해 표시된 문제를 해결할 수있는 우리의 통제가 아니기 때문에. – Gishu

+2

@ Gishu : 재산 세터가 예외를 던질 수 있다고 우려한다면, 그렇습니다. –

관련 문제