2014-09-30 50 views
0

我该如何排序“上传”,如果我有一个表达式Expression.Constant(3)Expression.Constant(3d),它会将int上变换为double?Linq.Expressions值类型隐式铸造

我知道我可以使用Expression.Convert()进行转换,但确定哪种类型可以隐式上传的最佳方法是什么?

我正在写一个简单的等式评估,所以只能期望的输入类型是值类型

+1

我不希望那里有任何获得给定'Type'在运行时可以隐式转换为的所有类型的列表的方式。您应该重新设计程序以避免出现这种情况,并且不要在运行时尝试这样做。 – Servy 2014-09-30 14:37:04

+0

你刚刚描述了一个编译器的工作,它知道这些基于C#语言规范的东西。 – fejesjoco 2014-09-30 14:56:54

+0

没有任何类型。只是价值类型 – 2014-09-30 15:29:03

回答

1

这里要考虑的关键问题是,System.Linq.Expressions,其被两个LINQ和动态语言运行时,被设计成一个语言无关代码模型。这个想法是为了创建一个可以将任意语言的表达式转换成LINQ/DLR树的“编译器”。不同的语言有自己的规则来管理隐式或显式的转换类型,因此表达式树API和编译器对于要求类型精确匹配的要求非常严格。 “编译器编写器”(或任何代码生成这些表达式树)的工作是显式注入需要匹配源语言语义的任何转换。

您的自定义表达式语言的语义取决于您;您可以选择将它们从现有语言(例如C#)中提取出来,但是您不会在LINQ/DLR框架中找到许多工具来告诉您“应该”隐式发生哪种类型的转换,因为没有标准的规则集这个;这样的规则是语言相关的。无论您决定什么规则,它最终都取决于您将必要的转换注入到表达式树中。这是一项不平凡的任务,并且没有“一刀切”的解决方案,只需发布​​到StackOverflow即可。

好的方面是,在你的树中使用“不必要的”Convert表达式的代价很小;如果从一种类型到另一种类型的字节码级别转换实际上是空操作,那么编译表达式时不会发出额外的字节码。

0

在浏览时通过反射的System.Linq.Expressions命名空间,我发现下面的方法我用了一个动态的,而不是办法。

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

您引用的方法在内部用于特定目的,并且您不应该认为您可以放弃显式的'Convert',因为此方法告诉您两种类型可以隐式转换。它最终取决于操作数的使用位置和方式。 – 2014-10-08 16:01:26