生成Expression.Assign设置十进制时发生异常?从十进制

时间:2018-06-19 18:40:18

标签: c# .net .net-core expression-trees

构建表达式时遇到一个有趣的问题。我进行了一些基本的类型强制转换检查,以确保完成最少的转换,但是,遇到了一个我没想到的问题。

当我尝试使用BinaryExpression生成Expression.Assign并且从decimaldecimal?时,我收到异常:

  

System.ArgumentException:'类型'System.Decimal'的表达式不能用于分配给'System.Nullable'1 [System.Decimal]

有人可以解释吗?考虑到以下结果为true:

typeof(decimal?).IsAssignableFrom(typeof(decimal))

预期分配应等于以下语句:

decimal? x = null;
decimal y = 10;
x = y;

有问题的代码:

private Expression BuildMapExpressionForValueMap(MemberInfo destinationProperty, MemberInfo sourceProperty)
{
    Expression assignmentExpression = Expression.PropertyOrField(_source, sourceProperty.Name);
    Type destinationType = destinationProperty.GetUnderlyingType();

    if (!destinationType.IsAssignableFrom(sourceProperty.GetUnderlyingType()))
    {
        assignmentExpression = BuildCastExpression(assignmentExpression, destinationType);
    }

    var expression = Expression.Assign(Expression.PropertyOrField(_destination, destinationProperty.Name)
                                     , assignmentExpression);


    return expression;
}

2 个答案:

答案 0 :(得分:4)

从非可空值类型到对应的可空类型都有隐式转换。您生成的表达式必须是显式的。无法生成将Int32分配给Int64类型的变量的表达式的原因相同。编译器显式生成转换调用,因此您不必这样做。试试看,您会看到的。

您必须添加转化。

var param = Expression.Variable(typeof(decimal?));
var value = Expression.Constant(20m, typeof(decimal));
var expr = Expression.Assign(param,
    //value // fails
    Expression.Convert(value, param.Type)
);

答案 1 :(得分:1)

编写常规C#代码时,编译器免费为您执行隐式转换。但是,在处理Linq.Expressions时,应显式定义每个类型强制转换。

检查此代码,它将y分配给x,然后将其打印到控制台:

var paramX = Expression.Parameter(typeof(decimal?), "x");
var paramY = Expression.Parameter(typeof(decimal), "y");

var lambda = Expression.Lambda<Action<decimal?, decimal>>(
    Expression.Block(
        Expression.Assign(paramX, Expression.Convert(paramY, typeof(decimal?)))
        , Expression.Call(typeof(Console), "WriteLine", new Type[0],
            Expression.Convert(paramX, typeof(decimal)))
        ),
    paramX, paramY);

lambda.Compile().Invoke(null, 10);

您可以找到一个演示here