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 currentObject
. (Inherited fromObject
.)
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
to combine two expressions or more, put every expression in brackets, and use: *?
In 2010, the Dynamic Type was introduced and that gave us the ability to create dynamic lambda expressions.
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.
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.
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.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With