没有为类型'System.Byte'和'System.Byte'定义二元运算符Add

时间:2011-08-18 11:47:16

标签: c# expression

我正在研究一个动态构造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,结果返回到字节,因此我不会引发异常。 我的问题是,在不知道类型的情况下执行添加操作的逻辑是什么,如果我需要处理浮点类型,则不丢失一些数据?

3 个答案:

答案 0 :(得分:2)

基本上我会有条件地测试每个操作数的Type以查看它是bytesbyte等,并在必要时引入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?)