【问题标题】:can someone further explain this C# code有人可以进一步解释这个 C# 代码吗
【发布时间】:2013-03-15 23:42:32
【问题描述】:

我正在使用来自http://www.albahari.com/nutshell/predicatebuilder.aspx 的 PredicateBuilder 类

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 表达式使用给定的表达式作为参数调用另一个 lambda 表达式。我们可以从第一个表达式的主体和第二个表达式的调用版本创建条件表达式。最后一步是将其包装在一个新的 lambda 表达式中。


如果我有

Predicate<Book> p1 = b => b.Title.Contains("economy");
Predicate<Book> p2 = b=>b.PublicationYear>2001;
Predicate chain = p1.And(p2);

我不太明白解释。有人可以解释一下上面扩展方法的代码是如何工作的吗? 谢谢

【问题讨论】:

  • 您不清楚哪一部分?你能详细说明一下吗?
  • 第二个表达式如何在第一行使用第一个参数调用的部分,然后是如何构造和返回 lambda 表达式。

标签: c#-4.0 lambda predicatebuilder


【解决方案1】:

让我们像这样重写方法体:

return Expression.Lambda<Func<T, bool>>(
    Expression.OrElse(
        expr1.Body,
        Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>())
    ),
    expr1.Parameters);

我们还应该记住,expr1 是您现有的表达式,它接受 T 并返回 bool。此外,虽然我们正在使用的表达式树实际上并没有任何事情(它们代表一些东西),但我以后将使用“do”,因为它有很多作用更容易阅读。从技术上讲,要让表达式树实际执行某些操作,您必须先 compile 它,然后调用生成的委托。

好的,那么我们这里有什么?这是一个 lambda 表达式,它采用 expr1 采用的任何参数(参见最后一行),其主体(根据 documentation)是

BinaryExpression 表示条件 OR 运算 仅当第一个操作数的计算结果为时才计算第二个操作数 假的。

第一个操作数是expr1.Body,这意味着结果函数(实际上不是函数,见上面的注释)计算expr1。如果结果是true,它会当场返回true。否则,它使用与传递给expr1 的参数相同的参数调用expr2(这意味着单个T 参数)并返回结果。

【讨论】:

  • ok 所以如果 expre1 返回 false,expr2 会使用 same 参数调用。这就是我错过的。
猜你喜欢
  • 2021-10-15
  • 2014-05-18
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多