Может кто-то дополнительно объяснить этот код C#
Я использую класс PredicateBuilder из http://www.albahari.com/nutshell/predicatebuilder.aspx
public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
}
этот метод расширения связывает предикаты с оператором OR. на странице объяснение говорит
Мы начнем с вызова второго выражения с параметрами первого выражения. Выражение Invoke вызывает другое лямбда-выражение, используя заданные выражения в качестве аргументов. Мы можем создать условное выражение из тела первого выражения и вызванной версии второго. Последний шаг - обернуть это в новое лямбда-выражение.
так что если, например, у меня есть
Predicate<Book> p1 = b => b.Title.Contains("economy");
Predicate<Book> p2 = b=>b.PublicationYear>2001;
Predicate chain = p1.And(p2);
Я не совсем получил объяснение. Может кто-нибудь объяснить, как работает код метода расширения выше? Спасибо
1 ответ
Давайте перепишем тело метода следующим образом:
return Expression.Lambda<Func<T, bool>>(
Expression.OrElse(
expr1.Body,
Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>())
),
expr1.Parameters);
Мы также должны помнить, что expr1
ваше существующее выражение, которое принимает T
и возвращает bool
, Кроме того, хотя деревья выражений, с которыми мы работаем, на самом деле ничего не делают (вместо этого они представляют что-то), я собираюсь использовать "делать" впредь, потому что это значительно облегчает чтение. Технически, чтобы дерево выражений действительно что-то делало, сначала нужно скомпилировать его, а затем вызвать полученный делегат.
Хорошо, так что у нас здесь? Это лямбда-выражение, которое принимает любые параметры expr1
занимает (см. последнюю строку) и чье тело, согласно документации, является
BinaryExpression
это представляет условную операцию ИЛИ, которая оценивает второй операнд, только если первый операнд оценивается как ложный.
Первый операнд expr1.Body
, что означает, что результирующая функция (а не функция, см. примечание выше) оценивает expr1
, Если результат true
это возвращается true
на месте. В противном случае, это вызывает expr2
с теми же параметрами, что и переданные expr1
(это означает, что один T
параметр) и возвращает результат этого.