以编程方式获取转换和输出运算符类型
Programmatically get cast and output Types of operator
在 C# 中,给定两个输入 Type
,是否可以确定运算符的输出 Type
和隐式向上转换 Type
?例如,考虑表达式 s + i
。假设我有以下信息:
short s;
int i;
Type leftType = typeof(short);
Type rightType = typeof(int);
我可以确定表达式 s + i
的以下信息吗?
Type leftUpcastType = typeof(int);
Type rightUpcastType = typeof(int);
Type outputType = typeof(int);
我显然可以通过对所有类型和运算符进行大量查找 table 来做到这一点,但可能有更简单的方法。理想情况下,这也适用于具有运算符重载的用户定义 类,但这是次要要求。
是的,您可以使用 dynamic
类型来实现。不过请记住,对于任何无法在 runtime 求和的内容,dynamic 都会抛出异常,因此您需要确保只传递有效值或包装在 try/catch.
var leftType = left.GetType();
var rightType = right.GetType();
var outputType = ((dynamic)left + (dynamic)right).GetType();
然后您可以根据此信息推断是否有一个、两个或两个对象都没有为操作转换。
执行此操作的最佳方法是检查表达式的 return 类型,该表达式将两个您感兴趣的类型的值相加。这样您就不必担心提供有效的 values 用于在运行时添加,当您只关心 return type.
您可以采用现有的表达式并沿着表达式树向下移动(如果有的话),或者执行如下操作:
static Type GetTypeOfSummation<T1, T2>()
{
var p1 = Expression.Parameter(typeof(T1), "t1");
var p2 = Expression.Parameter(typeof(T2), "t2");
LambdaExpression x = DynamicExpression.ParseLambda(new[] { p1, p2 }, null, "t1 + t2");
return x.Body.Type;
}
static void Main()
{
Console.WriteLine(GetTypeOfSummation<int, double>()); // System.Double
Console.WriteLine(GetTypeOfSummation<int, decimal>()); // System.Decimal
Console.WriteLine(GetTypeOfSummation<float, double>()); // System.Double
}
此泛型方法将 return 加法运算的类型,而不实际执行加法。
您当然也可以使用 Type
实例而不是泛型类型参数来执行此操作,如果这是您想要的:
static Type GetTypeOfSummation(Type t1, Type t2)
{
var p1 = Expression.Parameter(t1, "t1");
var p2 = Expression.Parameter(t2, "t2");
LambdaExpression x = DynamicExpression.ParseLambda(new[] { p1, p2 }, null, "t1 + t2");
return x.Body.Type;
}
需要说明的是,DynamicExpression
来自System.Linq.Dynamic
命名空间,可以参考:https://www.nuget.org/packages/System.Linq.Dynamic/
在 C# 中,给定两个输入 Type
,是否可以确定运算符的输出 Type
和隐式向上转换 Type
?例如,考虑表达式 s + i
。假设我有以下信息:
short s;
int i;
Type leftType = typeof(short);
Type rightType = typeof(int);
我可以确定表达式 s + i
的以下信息吗?
Type leftUpcastType = typeof(int);
Type rightUpcastType = typeof(int);
Type outputType = typeof(int);
我显然可以通过对所有类型和运算符进行大量查找 table 来做到这一点,但可能有更简单的方法。理想情况下,这也适用于具有运算符重载的用户定义 类,但这是次要要求。
是的,您可以使用 dynamic
类型来实现。不过请记住,对于任何无法在 runtime 求和的内容,dynamic 都会抛出异常,因此您需要确保只传递有效值或包装在 try/catch.
var leftType = left.GetType();
var rightType = right.GetType();
var outputType = ((dynamic)left + (dynamic)right).GetType();
然后您可以根据此信息推断是否有一个、两个或两个对象都没有为操作转换。
执行此操作的最佳方法是检查表达式的 return 类型,该表达式将两个您感兴趣的类型的值相加。这样您就不必担心提供有效的 values 用于在运行时添加,当您只关心 return type.
您可以采用现有的表达式并沿着表达式树向下移动(如果有的话),或者执行如下操作:
static Type GetTypeOfSummation<T1, T2>()
{
var p1 = Expression.Parameter(typeof(T1), "t1");
var p2 = Expression.Parameter(typeof(T2), "t2");
LambdaExpression x = DynamicExpression.ParseLambda(new[] { p1, p2 }, null, "t1 + t2");
return x.Body.Type;
}
static void Main()
{
Console.WriteLine(GetTypeOfSummation<int, double>()); // System.Double
Console.WriteLine(GetTypeOfSummation<int, decimal>()); // System.Decimal
Console.WriteLine(GetTypeOfSummation<float, double>()); // System.Double
}
此泛型方法将 return 加法运算的类型,而不实际执行加法。
您当然也可以使用 Type
实例而不是泛型类型参数来执行此操作,如果这是您想要的:
static Type GetTypeOfSummation(Type t1, Type t2)
{
var p1 = Expression.Parameter(t1, "t1");
var p2 = Expression.Parameter(t2, "t2");
LambdaExpression x = DynamicExpression.ParseLambda(new[] { p1, p2 }, null, "t1 + t2");
return x.Body.Type;
}
需要说明的是,DynamicExpression
来自System.Linq.Dynamic
命名空间,可以参考:https://www.nuget.org/packages/System.Linq.Dynamic/