Может кто-то дополнительно объяснить этот код 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 параметр) и возвращает результат этого.

Другие вопросы по тегам