Pourquoi une conversion est-elle nécessaire dans les arbres d'expression?

c# entity-framework expression-trees

Question

À partir de cette question que j’ai posée il ya 5 minutes, il est clair que le code suivant lève une exception, indiquant que

Exception non gérée: System.InvalidOperationException: l'opérateur binaire Equal n'est pas défini pour les types 'System.Nullable`1 [System.Int32]' et 'System.Int32'.

Code

public static void GetResultCollection<T>() {
        AccrualTrackingEntities db = new AccrualTrackingEntities();
        var result = db.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name + "s"));

        int? ItemTypeValue = 1;

        var param = Expression.Parameter(typeof(T));

        var lambda = Expression.Lambda<Func<T, bool>>(
            Expression.Equal(
                Expression.Property(param, "ProcInstId"),
                Expression.Constant(ItemTypeValue)),
            param);

        var list = result.Where(lambda).ToList();
    }

Ce code, cependant, avec le type explicitement répertorié dans Expression.Constant fonctionne

class Program {
    public static void GetResultCollection<T>() {
        AccrualTrackingEntities db = new AccrualTrackingEntities();
        var result = db.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name + "s"));

        int? ItemTypeValue = 1;

        var param = Expression.Parameter(typeof(T));

        var lambda = Expression.Lambda<Func<T, bool>>(
            Expression.Equal(
                Expression.Property(param, "ProcInstId"),
                Expression.Constant(ItemTypeValue, typeof(int?))),
            param);

        var list = result.Where(lambda).ToList();
    }

La question qui se pose est de savoir pourquoi Expression.Constant n’est pas capable de convertir implicitement à partir de int? à ... int?

Réponse acceptée

Les arbres d’expression fonctionnent à un niveau inférieur au code source normal - vous pouvez penser qu’ils fonctionnent au niveau de la sortie du compilateur plutôt que de l’ entrée . Donc, alors qu'il y a une conversion implicite de int en int? en C #, cette conversion doit être représentée en IL chaque fois que le compilateur l'utilise pour une méthode normale ... elle doit donc également être présente dans une représentation d'arborescence d'expression.

Cela dit, votre exemple n’est pas clair, étant donné que vous essayez d’utiliser un int (à savoir ItemTypeValue.Value ) comme valeur pour un int? constante, et nous ne savons pas non plus quel est le type de la propriété ItemType .

Un exemple court mais complet de ce que vous souhaiteriez travailler aiderait beaucoup.

EDIT: Ok, je pense que je suis avec vous maintenant. Le problème est que si vous utilisez

int? foo = 1;
Expression.Constant(foo);

puis cela appelle Expression.Constant(object) qui encadre la valeur de foo . À ce stade, Expression.Constant ne peut pas dire que c'était à l'origine un int? , parce que c'est maintenant une boîte int . C’est ainsi que fonctionne la boxe .NET:

int? foo = 1;
object o = foo;
Console.WriteLine(o.GetType()); // Prints System.Int32

Cette surcharge d' Expression.Constant détermine le type général de l'expression à partir de la valeur qui lui est donnée. Elle crée donc une expression int , alors que vous voulez vraiment un int? expression.

Pour gérer correctement les informations de type, vous devez utiliser la surcharge qui vous permet de spécifier le type:

int? foo = 1;
Expression.Constant(foo, typeof(int?));

Votre question ne précise toujours pas quel code fonctionne ou pas, mais j'espère que cela vous aidera ...



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi