Как проверить, являются ли два выражения <Func <T, bool >> одинаковыми
Можно ли узнать, совпадают ли два выражения?
Как и следующие четыре выражения:
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;
Тогда, по крайней мере, мы можем видеть, что:
Но могу ли я сделать что-нибудь, чтобы узнать это в моем коде?
Заглянул в библиотеку msdn, где говорится, что
Equals
: Определяет, соответствует ли указанный объект текущему Object
. (Унаследовано от Object
.)
который, как я полагаю, означает, что по крайней мере класс Expression не переопределил метод equals, чтобы стать Equableable? Итак, как бы вы это сделали? Или я слишком много спрашиваю?: Р
Ответы
Ответ 1
Вы можете посмотреть тип ExpressionEqualityComparer, который используется внутри Linq to db4o. Он реализует интерфейс IEqualityComparer <T> , поэтому он может использоваться для общих коллекций, а также для автономного использования.
Он использует тип ExpressionComparison для сравнения двух выражений для равенства и HashCodeCalculation, чтобы вычислить хэш-код из выражения.
Все это связано с посещением дерева выражений, поэтому может быть довольно дорогостоящим, если вы делаете это повторно, но оно также может быть весьма удобным.
Код доступен в GPL или dOCL
Например, здесь ваш тест:
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));
}
}
И он действительно печатает True, False, False.
Ответ 2
Как ленивый ответ, вы можете проверить ToString()
- он должен хотя бы указать, где они явно отличаются (хотя он будет включать в себя имя-var там, так что это должно быть одинаково).
Для точной проверки эквивалентности... гораздо сложнее - много работы, по множеству разных типов node.
Ответ 3
Мне кажется, что это может быть трудно сделать, за исключением самых простых случаев.
Например:
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;
Технически, они равны, но как его можно определить без оценки IEnuemrable, возвращаемого в каждом выражении?