2009-11-09 6 views
10

많은 행동의 C#을 사양에 가까운해야 ExpressionTrees 컴파일러처럼 보이지만 C#을 달리 어떤 enum-typedecimal의 변환에 대한 지원이 없습니다 :ExpressionTrees 버그입니까? # 2

using System; 
using System.Linq.Expressions; 

class Program 
{ 
    static void Main() 
    { 
    Func<decimal, ConsoleColor> converter1 = x => (ConsoleColor) x; 
    ConsoleColor c1 = converter1(7m); // fine 

    Expression<Func<decimal, ConsoleColor>> expr = x => (ConsoleColor) x; 

    // System.InvalidOperationException was unhandled 
    // No coercion operator is defined between types 
    // 'System.Decimal' and 'System.ConsoleColor'. 

    Func<decimal, ConsoleColor> converter2 = expr.Compile(); 

    ConsoleColor c2 = converter2(7m); 
    } 
} 

다른 거의 사용되지 않는 C#을 명시 적 변환, double -> enum-type을 등 C#에서 설명한대로 작동하지만 decimal -> enum-type은 작동하지 않습니다. 이거 버그 야?

답변

16

아마 버그 일 수 있으며 아마도 내 잘못입니다. 미안합니다.

십진수 변환은 런타임에 실제로 사용자 정의 변환으로 구현되지만 기본 제공 변환으로 처리되므로 컴파일러와 런타임에서 표현식 트리 코드를 올바르게 작성하는 것이 가장 어려운 부분 중 하나입니다. 컴파일러에 의해. Decimal은이 속성이있는 유일한 유형이므로 이러한 경우 분석기에 모든 종류의 특수 용도 장비가 있습니다. 사실 nullable enum from nullable decimal conversion을 처리하기 위해 분석기에 IsEnumToDecimalConversion이라는 메서드가 있습니다. 꽤 복잡한 특별한 경우.

어떤 경우는 다른 방법으로 간주하지 못하고 오히려 잘못된 코드가 생성되는 경우가 있습니다. 메모 주셔서 감사합니다; 나는 이것을 테스트 팀에 보내고, 우리는 재 경기를 할 수 있는지 알아볼 것이다. 확률은 선의의 버그로 밝혀지면 C# 4 초기 릴리스에서 수정되지 않을 것입니다. 이 시점에서 우리는 릴리스가 안정적 이도록 "컴파일러에 의해 감추어 진"버그만을 취하고 있습니다.

+0

나는 C# 언어를 만드는 데있어 인간이 해를 입었다는 것을 알지 못했다. –

+0

"10 진수 변환은 런타임에 사용자 정의 변환으로 구현되지만 컴파일러에서 기본 제공 변환으로 처리됩니다." , 왜 이렇게 했습니까? – Brian

+2

@Brian : 표현을 바꾸는 변환을 할 때, int를 double로 말할 때, 정확하게 그 변환을하는 일리노이 명령어가 있습니다. 십진법을 두 배로 할 때 실제로 변환을 수행 할 메소드를 호출하는 코드를 생성합니다. 십진수에 대한 내장 CLR 변환 명령은 없습니다. 그러나 * 언어 * 관점에서 우리는 십진수 변환이 내장형 언어 변환이되기를 원합니다. 우리는 내장형 및 사용자 제공 형 변환에 대해 다른 규칙을 가지고 있습니다. 그래서 우리는 소수의 장면 뒤에 무엇이 일어나고 있는지를 숨기기 위해 특별한 풍경을 만들어야합니다. –

3

아직 아니 진짜 대답, 내가 조사하고 있습니다,하지만 첫 번째 라인으로 컴파일 : 이전 람다에서 식을 만들려고하면, 그것은 작동합니다

Func<decimal, ConsoleColor> converter1 = x => (ConsoleColor)(int)x; 

.

편집 : C#을 사양, §6.2.2에서, 당신은 읽을 수 둘 사이의 유형이 처리되는

명시 적 열거 형 변환을 에서의 기본 유형으로 참가하는 열거 형 치료 그 enum-type을 입력 한 다음 형식간에 암시 적 또는 명시적인 숫자 변환을 수행하십시오. 예를 들어, int 형의 int 형을 가지는 E를 지정하면, 에서 E 로의 변환은 int에서 byte까지의 명시적인 수치 변환 (§6. 2. 1), 및 바이트에서 의 명시적인 수치 변환 로서 처리됩니다. ~ E는 으로 처리되어 바이트에서 int로 암시 적 숫자 변환 (§6.1.2)으로 처리됩니다.

그래서 enum에서 decimal 로의 명시적인 캐스트가 특별히 처리되므로 그 중첩 된 캐스트 (int와 십진수)를 얻을 수 있습니다. 하지만 컴파일러가 두 경우 모두 람다 본문을 같은 방식으로 구문 분석하지 않는 이유는 알 수 없습니다.

+2

컴파일러는 다른 패스에서 중첩 된 캐스트를 방출합니다. 이 경우, 런타임시 실패하는 변환 노드 만 작성합니다. 중첩 된 변환을 발생시켜야하는 컴파일러 버그 또는 decimal에서 enum으로 변환해야하는 Expression API 버그가 독자에게 남겨집니다. 나는 적절한 전환 노드를 방출하는 것이 csc의 책임이라고 생각합니다. –

+0

동의합니다.사실 "expr = lambda"줄에 컴파일 오류가 발생합니다. 그래서 컴파일러는 추가적인 Convert 노드 나 다른 것을 실제로 내보내려고하지 않습니다. 그것은 람다 바디가 C# 스펙에 따라 유효하지 않은 것으로 간주합니다. –

+0

'double -> enum-type' 변환의 경우 csc가'double -> int' 변환을하지 않고'double -> enum-type '을 직접 호출하고 ExpressionTrees 컴파일러가이 잘 알고 있습니다 ... – ControlFlow