44 votes

Comment vérifier si deux expressions <Func<T, bool> > sont les mêmes

Est-il possible de savoir si deux expressions sont les mêmes?

Étant donné les quatre expressions:

        Expression<Func<int, bool>> a = x => false;
        Expression<Func<int, bool>> b = x => false;
        Expression<Func<int, bool>> c = x => true;
        Expression<Func<int, bool>> d = x => x == 5;

Alors, au moins nous pouvons voir que:

  • a == b
  • a != c
  • a != d

Mais ce que je peux faire quelque chose pour trouver ceci dans mon code?

A pris un coup d'oeil dans la bibliothèque msdn, où il est dit que

Equals: Détermine si l'Objet spécifié est égal au courant Object. (Hérité de l' Object.)

qui je suppose signifie qu'au moins l'Expression de la classe n'a pas surdéfini la méthode equals pour devenir Equatable? Alors, comment le feriez-vous? Ou suis-je trop demander ici? :p

35voto

Jb Evain Points 11368

Vous pouvez avoir un regard sur le type de ExpressionEqualityComparer qui est utilisé à l'intérieur de Linq to db4o. Il implémente l'interface IEqualityComparer<T>, il est donc utilisable pour les collections, ainsi que pour une utilisation autonome.

Il utilise le type de ExpressionComparison pour comparer deux Expressions pour l'égalité, et HashCodeCalculation, pour calculer un hashcode à partir d'une Expression.

Elle implique tous les visitant l'expression de l'arbre, de sorte qu'il peut être assez cher si vous le faites à plusieurs reprises, mais il peut également être très pratique.

Le code est disponible sous la licence GPL ou le dOCL

Par exemple, voici votre test:

using System;
using System.Linq.Expressions;

using Db4objects.Db4o.Linq.Expressions;

class Test {

    static void Main ()
    {
    	Expression<Func<int, bool>> a = x => false;
    	Expression<Func<int, bool>> b = x => false;
    	Expression<Func<int, bool>> c = x => true;
    	Expression<Func<int, bool>> d = x => x == 5;

    	Func<Expression, Expression, bool> eq =
    		ExpressionEqualityComparer.Instance.Equals;

    	Console.WriteLine (eq (a, b));
    	Console.WriteLine (eq (a, c));
    	Console.WriteLine (eq (a, d));
    }
}

Et en effet, elle imprime True, False, False.

17voto

Marc Gravell Points 482669

En guise de réponse paresseuse, vous pouvez vérifier ToString() - il devrait au moins indiquer où elles sont clairement différentes (bien que le nom de la variable y soit inclus, il devrait donc être identique).

Pour vérifier l'équivalence avec précision ... beaucoup plus difficile - beaucoup de travail, sur beaucoup de types de nœuds différents.

4voto

Dustin Campbell Points 6323

Il me semble que cela pourrait être difficile à faire, sauf dans les cas les plus simples.

Par exemple:

 var numbers1 = Enumerable.Range(1, 20);
Expression<Func<int, IEnumerable<int>>> a = x => numbers1;
var numbers2 = Enumerable.Range(1, 20);
Expression<Func<int, IEnumerable<int>>> b = x => numbers2;
 

Techniquement, ils sont égaux, mais comment pourrait-on le déterminer sans évaluer l’iEnuemrable renvoyé dans chaque expression?

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