Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if two Expression<Func<T, bool>> are the same [duplicate]

Is it possible to find out if two expressions are the same?

Like given the following four 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;

Then, at least we can see that:

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

But can I do anything to find this out in my code?

Took a peek in the msdn library, where it says that

Equals: Determines whether the specified Object is equal to the current Object. (Inherited from Object.)

which I guess means that at least the Expression class hasn't overrided the equals method to become Equatable? So how would you do this? Or am I asking too much here? :p

like image 307
Svish Avatar asked Mar 23 '09 12:03

Svish


People also ask

How do you combine two expressions?

to combine two expressions or more, put every expression in brackets, and use: *?

Can we use dynamic in lambda expressions?

In 2010, the Dynamic Type was introduced and that gave us the ability to create dynamic lambda expressions.

What is Expression C#?

An expression in C# is a combination of operands (variables, literals, method calls) and operators that can be evaluated to a single value. To be precise, an expression must have at least one operand but may not have any operator.


3 Answers

You can have a look at the type ExpressionEqualityComparer that is used inside Linq to db4o. It implements the interface IEqualityComparer<T>, so it's usable for generic collections, as well as for a standalone usage.

It uses the type ExpressionComparison to compare two Expressions for equality, and HashCodeCalculation, to compute a hashcode from an Expression.

It all involves visiting the expression tree, so it can be pretty costly if you do it repeatedly, but it can also be quite handy.

The code is available under the GPL or the dOCL

For instance, here's your 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));
    }
}

And it indeed prints True, False, False.

like image 67
Jb Evain Avatar answered Oct 20 '22 01:10

Jb Evain


As a lazy answer, you can check ToString() - it should at least indicate where they are clearly different (although it will include the var-name in there, so that would have to be the same).

For checking equivalence accurately... much harder - a lot of work, over a lot of different node types.

like image 20
Marc Gravell Avatar answered Oct 20 '22 01:10

Marc Gravell


It strikes me that this might be difficult to do, except in the simplest of cases.

For example:

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;

Technically, these are equal, but how could it be determined without evaluating the IEnuemrable returned in each expression?

like image 4
Dustin Campbell Avatar answered Oct 20 '22 01:10

Dustin Campbell