Explicit listing in expression tree?

Consider the class MyDecimalbelow. In C#we can apply it to an integer thanks to the implicit operator decimal:

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

How do you create equivalent code in an expression tree?

When using Expression.Convert ( .NET 4.5.1), it immediately fails with No coercion operator is defined between types 'System.Int32' and 'MyDecimal'. It seems to consider only implicit cast operators.

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

MyDecimal class:

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);
    }
}
+4
source share
2 answers

It is always interesting, for example, the expression tree of the Lambda expression, which does the same:

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

Using the LinqPad tool link, we can check the conversion and see that we have the following:

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

, decimal int, , 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 .
+4

, , :

class Program
{
    static void Main(string[] args)
    {
        MyDecimal myDecimal = new MyDecimal(123.123m);
        myDecimal = 123.123m;
        int i = (int)myDecimal;
        i = myDecimal.ToInt();
        i = myDecimal.ToIntExpression();
    }


    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);
        }

        public int ToInt()
        {
            return Convert.ToInt32(this.value);
        }

        public int ToIntExpression()
        {
            return Convert.ToInt32(Expression.Constant(this.value, typeof(decimal)).Value);
        }
    }

}
0

Source: https://habr.com/ru/post/1685730/


All Articles