2014-09-30 3 views
0

Expression.Constant(3)Expression.Constant(3d)이라는 표현식을 사용하면 정수를 double로 상향 변환 할 수있는 방법을 "위로 캐스트"할 수 있습니까?Linq.Expressions 값 형식 암시 적 캐스팅

나는 Expression.Convert()을 사용하여 변환 할 수 있지만 어떤 유형이 암시 적으로 상영 될 수 있는지를 결정하는 가장 좋은 방법은 무엇입니까?

나는 간단한 방정식 평가를 쓰고 있어요, 그래서 리플렉터의 System.Linq.Expressions 네임 스페이스를 통해 검색하는 중에 유일한 예상되는 입력 유형이

+1

주어진'Type'이 런타임에 암시 적으로 변환 될 수있는 모든 유형의 목록을 가져 오는 * 방법이있을 것으로 기대하지는 않습니다. 첫 번째 상황을 피하기 위해 프로그램을 다시 디자인하고 런타임에이를 시도하지 않아야합니다. – Servy

+0

방금 ​​컴파일러의 작업에 대해 설명했습니다.이 작업은 C# 언어 사양을 기반으로합니다. – fejesjoco

+0

유형 없음. Just Value Types –

답변

1

여기에서 고려해야 할 중요한 점은 LINQ 및 동적 언어 런타임에서 모두 사용 System.Linq.Expressions가하는 언어에 독립적 코드 모델로 설계되어 있다는 점이다. 아이디어는 임의의 언어에서 표현을 LINQ/DLR 트리로 변환 할 수있는 "컴파일러"를 만드는 것이 가능하도록 만드는 것입니다. 서로 다른 언어에는 암시 적 또는 명시 적으로 발생하는 변환의 종류를 관리하는 고유 한 규칙이 있으므로 표현식 트리 API 및 컴파일러는 유형을 정확히 일치시키는 데 매우 엄격한 경향이 있습니다. 소스 언어 의미와 일치시키기 위해 필요한 변환을 명시 적으로 주입하는 것은 "컴파일러 작성자"(또는이 표현 트리를 생성하는 코드)의 임무입니다.

사용자 지정 표현식 언어의 의미는 사용자가 결정합니다. C#과 같은 기존 언어를 기반으로 선택할 수 있지만 LICQ/DLR 프레임 워크 내에서 암시 적으로 발생해야하는 변환 유형을 알려주는 많은 기능을 찾을 수 없습니다. 에는 표준 규칙 집합이 없습니다. 이; 이러한 규칙은 언어에 따라 다릅니다. 결정한 규칙이 무엇이든 궁극적으로 필요한 변환을 표현식 트리에 삽입하는 것은 사용자의 몫입니다. 이것은 단순한 작업이 아니며 단순히 StackOverflow에 게시 할 수있는 "모든 크기에 맞는"솔루션은 없습니다.

위쪽에있는 "불필요한"Convert 표현을 트리에 넣는 데 드는 비용은 거의 들지 않습니다. 한 유형에서 다른 유형으로의 바이트 코드 레벨 변환이 사실상 no-op 일 경우, 표현식이 컴파일 될 때 추가 바이트 코드는 방출되지 않습니다.

0

을 값 종류는 내가 동적 대신 사용되는 다음과 같은 방법을 발견 방법.

public static bool IsImplicitNumericConversion(Type source, Type destination) 
    { 
     TypeCode typeCode = Type.GetTypeCode(source); 
     TypeCode code2 = Type.GetTypeCode(destination); 
     switch (typeCode) 
     { 
      case TypeCode.Char: 
       switch (code2) 
       { 
        case TypeCode.UInt16: 
        case TypeCode.Int32: 
        case TypeCode.UInt32: 
        case TypeCode.Int64: 
        case TypeCode.UInt64: 
        case TypeCode.Single: 
        case TypeCode.Double: 
        case TypeCode.Decimal: 
         return true; 
       } 
       return false; 

      case TypeCode.SByte: 
       switch (code2) 
       { 
        case TypeCode.Int16: 
        case TypeCode.Int32: 
        case TypeCode.Int64: 
        case TypeCode.Single: 
        case TypeCode.Double: 
        case TypeCode.Decimal: 
         return true; 
       } 
       break; 

      case TypeCode.Byte: 
       switch (code2) 
       { 
        case TypeCode.Int16: 
        case TypeCode.UInt16: 
        case TypeCode.Int32: 
        case TypeCode.UInt32: 
        case TypeCode.Int64: 
        case TypeCode.UInt64: 
        case TypeCode.Single: 
        case TypeCode.Double: 
        case TypeCode.Decimal: 
         return true; 
       } 
       return false; 

      case TypeCode.Int16: 
       switch (code2) 
       { 
        case TypeCode.Int32: 
        case TypeCode.Int64: 
        case TypeCode.Single: 
        case TypeCode.Double: 
        case TypeCode.Decimal: 
         return true; 
       } 
       return false; 

      case TypeCode.UInt16: 
       switch (code2) 
       { 
        case TypeCode.Int32: 
        case TypeCode.UInt32: 
        case TypeCode.Int64: 
        case TypeCode.UInt64: 
        case TypeCode.Single: 
        case TypeCode.Double: 
        case TypeCode.Decimal: 
         return true; 
       } 
       return false; 

      case TypeCode.Int32: 
       switch (code2) 
       { 
        case TypeCode.Int64: 
        case TypeCode.Single: 
        case TypeCode.Double: 
        case TypeCode.Decimal: 
         return true; 
       } 
       return false; 

      case TypeCode.UInt32: 
       switch (code2) 
       { 
        case TypeCode.UInt32: 
        case TypeCode.UInt64: 
        case TypeCode.Single: 
        case TypeCode.Double: 
        case TypeCode.Decimal: 
         return true; 
       } 
       return false; 

      case TypeCode.Int64: 
      case TypeCode.UInt64: 
       switch (code2) 
       { 
        case TypeCode.Single: 
        case TypeCode.Double: 
        case TypeCode.Decimal: 
         return true; 
       } 
       return false; 

      case TypeCode.Single: 
       return (code2 == TypeCode.Double); 

      default: 
       return false; 
     } 
     return false; 
    } 
+0

참조하는 메소드는 특정 목적을 위해 내부적으로 사용되며,이 메소드는 암시 적으로 변환 할 수있는 두 가지 유형을 알려주기 때문에 명시 적으로 '변환'을 수행 할 수 없다고 가정하면 안됩니다. 궁극적으로 피연산자가 어디서 어떻게 사용되는지에 달려 있습니다. –