表达式树中的显式强制转换?

时间:2017-09-15 08:15:34

标签: c#

考虑下面的MyDecimal课程。在C#中,由于隐式decimal运算符,我们可以将其转换为整数:

int i = (int)new MyDecimal(123m);

如何在表达式树中生成等效代码?

使用Expression.Convert.NET 4.5.1)时,它会立即失败并显示No coercion operator is defined between types 'System.Int32' and 'MyDecimal'。它似乎只考虑隐式转换运算符。

try
{
    var param = Expression.Parameter(typeof(int), null);
    var convert = Expression.Convert(param, typeof(MyDecimal));
}
catch (Exception ex)
{
}

MyDecimal上课:

public class MyDecimal
{
    private readonly decimal value;

    public MyDecimal(decimal value)
    {
        this.value = value;
    }

    public static implicit operator decimal(MyDecimal myDecimal)
    {
        return myDecimal.value;
    }

    public static implicit operator MyDecimal(decimal value)
    {
        return new MyDecimal(value);
    }
}

1 个答案:

答案 0 :(得分:4)

示例表达Lambda的表达式树的例子总是很有趣:

Expression<Func<MyDecimal,int>> convert = m => (int)m;

使用工具链接LinqPad,我们可以检查转换,看看我们有以下内容:

Expression<Func<MyDecimal,int>> (type: Lambda)
|
+-  UnaryExpression (type:Convert) - Convert(int, decimal)
    |
    +- UnaryExpression (type:Convert) - Convert(decmal, MyDecimal)

因此,虽然编译器允许从decimalint的隐式转换,但您可以看到等效的Lambda要求转换是显式的。

<强> 修改

因此,要构建完整的表达式,您需要具备以下内容:

        Expression.Assign(
            Expression.Variable(typeof(int), "i"),
            Expression.Convert(
                Expression.Convert(
                    Expression.New(
                        typeof(MyDecimal).GetConstructor(new[] {typeof(decimal)}),
                        Expression.Convert(
                            Expression.Constant(1),
                            typeof(decimal)
                        )
                    ),
                    typeof(decimal)),
                typeof(int)
            )
        )

需要注意的一些要点:

  • 我们正在将int 1转换为decimal以传递给构造函数
  • 我们必须使用正确的类型参数查找构造函数(我欺骗并假设它是公开的)
  • 我们假设i已经宣布。