我怎样排序" up-cast"如果我有一个表达式Expression.Constant(3)
和Expression.Constant(3d)
,它会将int上转换为double?
我知道我可以使用Expression.Convert()
转换,但是确定哪种类型可以隐式上传的最佳方法是什么?
我正在编写一个简单的等式计算器,因此唯一预期的输入类型是值类型
答案 0 :(得分:1)
这里要考虑的关键是LINQ和动态语言运行时使用的System.Linq.Expressions
被设计为与语言无关的代码模型。我们的想法是创建一个"编译器"可以将任意语言的表达式转换为LINQ / DLR树。不同的语言有自己的规则来管理隐式或显式发生的转换类型,因此表达式树API和编译器在要求类型完全匹配时往往非常严格。这是"编译器编写器"的工作。 (或者生成这些表达式树的任何代码)以显式注入与源语言语义匹配所需的任何转换。
您的自定义表达式语言的语义由您决定;你可以选择以C#之类的现有语言为基础,但你不会在LINQ / DLR框架中找到很多设施来告诉你哪种类型的转换"应该"隐式发生,因为没有标准的规则集;这些规则与语言有关。无论您决定采用哪种规则,最终都需要将必要的转换注入表达式树。这是一项非常重要的任务,并且没有任何一种尺寸适合所有"可以简单地发布到StackOverflow的解决方案。
从好的方面来说,没有必要花费很少的成本。树中的Convert
个表达式;如果从一种类型到另一种类型的字节码级转换实际上是无操作,则在编译表达式时不会发出额外的字节码。
答案 1 :(得分:0)
浏览Reflector中的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;
}