2011-11-22 3 views
11

나는 다음과 같은 코드를 매우 이상한 C# 컴파일러 동작을 발견했습니다이상한 C# 컴파일러 동작 (오버로드 확인)

Expected: 0 
    But was: null 

나는 이유를 이해 :

var p1 = new SqlParameter("@p", Convert.ToInt32(1)); 
    var p2 = new SqlParameter("@p", 1); 
    Assert.AreEqual(p1.Value, p2.Value); // PASS 

    var x = 0; 
    p1 = new SqlParameter("@p", Convert.ToInt32(x)); 
    p2 = new SqlParameter("@p", x); 
    Assert.AreEqual(p1.Value, p2.Value); // PASS 

    p1 = new SqlParameter("@p", Convert.ToInt32(0)); 
    p2 = new SqlParameter("@p", 0); 
    Assert.AreEqual(p1.Value, p2.Value); // FAIL!? 

마지막 라인 어설에서 다음 메시지와 함께 실패 테스트가 실패합니다 : p2 = new SqlParameter("@p", 0);SqlParameter(string, SqlDbType)으로, 다른 경우에는 SqlParameter(string, object)으로 해결됩니다. 그러나 나는 이것이 왜 일어나는 지 이해하지 못합니다. 내게는 버그처럼 보이지만, C# 컴파일러가 이런 종류의 버그를 가질 수 있다고 믿을 수 없다.

이유가 있으십니까?

P. 열거 형 매개 변수와 0 값 (SqlDbType은 열거 형)을 사용하여 모든 메서드 오버로드에 문제가있는 것 같습니다.

답변

11

기본적으로 십진 정수 리터럴 0은 암시 적으로 모든 열거 형 (C# 4 사양 §6.1.3)으로 변환되므로 컴파일러에서 SqlParameter(string, SqlDbType)이 해당 함수 멤버임을 결정합니다. 그러면 두 개의 후보 함수 멤버 중에서 더 나은 것을 선택해야하며 SqlDbTypeobject (7.5.3.2)보다 특정한 유형이므로 SqlParameter(string, object)을 통해 SqlParameter(string, SqlDbType)을 선택합니다.

하지만이 경우 매우 혼란 스럽습니다 ...

+0

경고 수준을 최대로 설정하면 어떻게됩니까? 아마도이 경우 경고 할 것입니다. – dowhilefor

+0

Yeap, 알아 들었어. 내 질문은 : 그것은 단지 0에 대해서만 작동합니까? –

+5

@VictorHaydin, 왜냐하면 사양에서 이렇게 말하기 때문입니다 ... "암묵적인 열거 형 변환은 10 진수 - 정수 - 리터럴 0을 모든 enum 유형 및 기본 유형이 enum 유형 인 임의의 null 가능 유형으로 변환 할 수있게합니다." 자, 왜 이런 식으로 설계되었는지 모르겠지만, 아마도 좋은 이유가 있습니다 ... 당신은 C# 팀의 누군가에게 물어볼 필요가 있습니다. –