Lambda表达式以及如何将它们组合起来?

时间:2010-07-20 08:12:31

标签: c# .net linq generics lambda

如何使用OR?

将两个lambda表达式合并为一个

我尝试过以下但是合并它们需要我将参数传递给 Expression.Invoke 调用,但是我想将传递给新lambda的值传递给每个child-lambda。

Expression<Func<int, bool>> func1 = (x) => x > 5;
Expression<Func<int, bool>> func2 = (x) => x < 0;
//Combines the lambdas but result in runtime error saying I need to pass in arguments
//However I want the argument passed into each child lambda to be whatever is passed into the new main lambda
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(Expression.Or(Expression.Invoke(func1), Expression.Invoke(func2)));

 //The 9 should be passed into the new lambda and into both child lambdas
 bool tst = lambda.Compile().Invoke(9);

如何将两个lambda表达式合并为一个并将子lambdas的参数组合成父类的参数?

4 个答案:

答案 0 :(得分:18)

我发现学习表达式的最佳方法是查看PredicateBuilder的源代码。

如果要组合多个语句,可以:

Expression<Func<int, bool>> func1 = (x) => x > 5;
Expression<Func<int, bool>> func2 = (x) => x > 10;

var invocation = Expression.Invoke(func2, func1.Parameters.Cast<Expression>());
var expression = Expression.Lambda<Func<int, bool>>(Expression.OrElse(func1.Body, invocation), func1.Parameters);

Expression.Invoke创建一个InvocationExpression,将参数应用于func2

事实上,PredicateBuilder可能就是你需要的一切。

var predicate = PredicateBuilder.False<int>();
predicate = predicate.Or(x => x > 5);
predicate = predicate.Or(x => x > 10);

我会修改“x > 5x > 10”,对OR来说似乎很奇怪。

希望有所帮助。

答案 1 :(得分:1)

听起来很有趣......我对lambda表达不太了解,但我发现this article。在 PredicateBuilder源代码下是适用于我的的示例:

public static Expression<Func<T, bool>> Or<T>(
                      this Expression<Func<T, bool>> expr1,
                      Expression<Func<T, bool>> expr2 )
{
  var invExpr = Expression.Invoke( expr2, expr1.Parameters.Cast<Expression>() );
  return Expression.Lambda<Func<T, bool>>
      ( Expression.OrElse( expr1.Body, invExpr ), expr1.Parameters );
}

答案 2 :(得分:1)

为什么不这样做:

Func<int, bool> func1 = (x) => x > 5;
Func<int, bool> func2 = (x) => x > 10;

List<Func<int, bool>> funcs = new List<Func<int, bool>> { func1, func2 };

var value = 7;

Console.WriteLine(funcs.Any(x => x(value))); // OR
Console.WriteLine(funcs.All(x => x(value))); // AND

避免与第三方库混淆。

答案 3 :(得分:0)

**编辑:oops读取OR事物,更新它***

您好,

不确定您是否只想将它们称为seperatley,或者您想从学术角度将它们结合起来。

你可以像这样打电话给他们:

bool OR(int i1, Func<int, bool> f1, Func<int, bool> f2){
    return f1(i1) || f2(i1);
}

这样就可以了。

或者您可以将其重写为

bool MyOR = (i1, f1, f2) => f1(i1) || f2(i1);

当你很谨慎的时候,从中创建一个表达式并查看它。 (手动完成这个,现在不要在这里使用VS,所以请在我的拼写错误中轻松完成)

Expression<Func<int, Func<int, bool>, Func<int, bool>, bool>> exprOR = 
(i1, f1, f2) => f1(i1) || f2(i1); 

如果你想看一下表达式的解剖,你可以看看我写的这篇文章:http://www.codeproject.com/KB/WPF/WpfExpressionTree.aspx

将表达式传递给apadater并查看它是如何构建的。

关心Gert-Jan