4 votes

Distribution explicite dans l'arbre d'expression ?

Considérez le MyDecimal classe ci-dessous. Sur C# nous pouvons le convertir en un nombre entier grâce à la fonction implicite decimal opérateur :

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

Comment produire le code équivalent dans un arbre d'expression ?

Lorsque vous utilisez Expression.Convertir ( .NET 4.5.1 ), il échoue immédiatement avec No coercion operator is defined between types 'System.Int32' and 'MyDecimal' . Il semble ne prendre en compte que les opérateurs de cast implicites.

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

MyDecimal classe :

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

4voto

David Kemp Points 5711

Il est toujours intéressant d'illustrer l'arbre d'expression d'une Expression Lambda qui fait la même chose :

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

En utilisant un lien d'outil LinqPad, nous pouvons examiner convert et voir que nous avons ce qui suit :

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

Ainsi, bien que le compilateur permet la conversion implicite de decimal a int vous pouvez voir que l'équivalent Lambda exige que la conversion soit explicite.

EDITAR

Donc, pour construire l'expression complète, vous devez avoir quelque chose comme :

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

Quelques points à noter :

  • Nous convertissons le int 1 à decimal à passer au constructeur
  • Nous devons rechercher le constructeur avec les paramètres de type corrects (je triche et suppose qu'il est public).
  • Nous supposons i est déjà déclaré.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X