我正在研究一个动态构造lambda表达式的项目。 在特定场景中,我动态构造了一个等于这个的表达式:
字节i = 1;
字节j = 1;
var firstConstant = Expression.Constant(i);
var secondConstant = Expression.Constant(j);
var lambda = Expression.Lambda(Expression.Add(firstConstant,secondConstant));
。lambda.Compile()DynamicInvoke();
我知道原始类型没有运算符重载,编译器实际上在添加之前将变量/常量转换为int,结果返回到字节,因此我不会引发异常。 我的问题是,在不知道类型的情况下执行添加操作的逻辑是什么,如果我需要处理浮点类型,则不丢失一些数据?
答案 0 :(得分:2)
基本上我会有条件地测试每个操作数的Type
以查看它是byte
,sbyte
等,并在必要时引入Expression.Convert
。
可能值得查看C#编译器为其生成的内容:
Expression<Func<byte, byte, int>> expr = (a, b) => a + b;
...然后尝试获取自己的代码以生成正确的内容。
答案 1 :(得分:1)
试
byte i = 1;
byte j = 1;
var firstConstant = Expression.Constant(i.GetType () == typeof (Byte) ? (int) i : i);
var secondConstant = Expression.Constant(j.GetType () == typeof (Byte) ? (int) j : j);
var lambda = Expression.Lambda(Expression.Add(firstConstant, secondConstant));
lambda.Compile().DynamicInvoke();
这样,如果它不是一个字节,你就不会丢失任何东西......
另请注意,执行byte r = i + j;
会给出关于“没有从int到byte的自动转换”的编译时错误。
答案 2 :(得分:0)
这可能是不可能的。 Expression.Add不执行溢出检查,它查找Binary +运算符的实现。另一个重载允许指定MethodInfo以选择执行Add的方法。
如果您可以确保所有类型都进入,请支持此方法,您可以使用上述逻辑。它确实有效,因为定义了二元+运算符。 System.Byte类不存在相同的问题,因此您遇到了问题。即使使用Compiler实现,也无法做到:
byte i = 1;
byte j = 2;
byte sum = i+j; // Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)