c# - 理解 Expression.Invoke() 方法

标签 c# expression-trees

我一直在理解PredicateBuilder Joseph Albahari 编写的扩展方法,我看到了这个 Expression.Invoke老实说,我无法通过以下方法理解它的原因:

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);
}

虽然他稍微解释了一下:

The interesting work takes place inside the And and Or methods. We start by invoking the second expression with the first expression’s parameters. An Invoke expression calls another lambda expression using the given expressions as arguments. We can create the conditional expression from the body of the first expression and the invoked version of the second. The final step is to wrap this in a new lambda expression.

MSDN告诉我:

Creates an InvocationExpression that applies a delegate or lambda expression to a list of argument expressions.

这对我来说有点意义。所以如果我使用这样的表达式,基本上我不必传入任何参数。

但不知为何我不太明白。也许我累了或什么的。

问题:

  1. 何时何地使用 InvocationExpression 是有意义的.
  2. 谁能解释一下 Or<T>方法(或 AndElse<T>)方法效果好一点?

更新:

我在想InvocationExpression当我下类回家的时候,它在我的脑海里暗示着:

当我们调用一个方法时,我们简单地说CallMe(phoneNumber, time);这称为方法调用。然后,InvocationExpression应该是表达 CallMe(phoneNumber, time); 的表达式.它类似于 LambdaExpression表示一个 lambda,例如 t => t + 2 .所以基本上它是一个应用于参数(而不是参数)的方法调用。因此作为调用,它不再需要参数,但可能会返回一些东西,因为参数已经应用于它的参数。

有关我正在谈论的代码的更多信息,请访问 http://www.albahari.com/nutshell/predicatebuilder.aspx

最佳答案

想象一下,您不是在处理表达式,而是在处理委托(delegate)。然后你可以这样写 Or:

public static Func<T, bool> Or<T>(this Func<T, bool> expr1, Func<T, bool> expr2)
{
    return x => expr1(x) || expr2(x);
}

您创建一个新的委托(delegate)来调用这两个委托(delegate),并使用 || 进行组合。当您重写它以使用表达式时,调用委托(delegate)会变成 Expression.Invoke():

public static Expression<Func<T, bool>> Or<T>(
    this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
    var parameter = Expression.Parameter(typeof(T), "x");
    var invokedExpr1 = Expression.Invoke(expr1, parameter);
    var invokedExpr2 = Expression.Invoke(expr2, parameter);

    return Expression.Lambda<Func<T, bool>>(
        Expression.OrElse(invokedExpr1, invokedExpr2), parameter);
}

实际的 Or 不是这样写的原因(很可能)是一种优化:您不必调用两个表达式,您可以重用其中一个的正文和参数他们。 (但是你不能重用它们,因为它们有不同的参数。)

关于c# - 理解 Expression.Invoke() 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19870313/

相关文章:

c# - 如何替换表达式树中的类型参数?

linq - 打印出 Linq 表达式树层次结构

c# - 修改动态属性选择器 Lambda

c# - WPF:Content 和 DataContext 属性之间有什么区别?

c# - UWP Entity Framework Core SQLITE 在 Release模式下崩溃

c# - 关于 ComboBoxes、ValueMember 和 DisplayMember 的一些混淆

c# - 在 C# 中查找匹配的单词

c# - 在没有单独的 try-catch block 的情况下 try catch 每一行代码

c# - 动态生成一个 Action

c# - 将取消 token 传递给调用方法 VS 任务构造函数?