Lambda 表达式以及如何组合它们?
Posted
技术标签:
【中文标题】Lambda 表达式以及如何组合它们?【英文标题】:Lambda expressions and how to combine them? 【发布时间】:2011-03-18 07:33:15 【问题描述】:如何使用 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 表达式组合为一个并让子 lambda 的参数成为父 lambda 的参数?
【问题讨论】:
当你说“结合”时,你真正想要发生的事情是什么?假设传递的参数是7
- func1
将返回 true,func2
将返回 false。您希望组合返回什么?
【参考方案1】:
我发现学习表达式的最好方法是看一下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 > 5
或 x > 10
”,这对 OR 来说似乎很奇怪。
希望对您有所帮助。
【讨论】:
太好了,这正是我想要的。 'Expression.Lamda' 缺少一个 'b',所以应该是 .Expression.Lambda' 顺便说一句,Linq to Entities 不支持Expression.Invoke
。因此,尽管这将编译为 IL。它不会编译成 SQL。【参考方案2】:
听起来很有趣……我对 lambda 表达式了解不多,但我找到了this article。在 PredicateBuilder Source Code 下是一个适合我的 or 示例:
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 );
【讨论】:
【参考方案3】:为什么不直接做:
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
?
省去了使用 3rd 方库的麻烦。
【讨论】:
问题是我想把它们保存在一个表达式树中,所以它们被实体框架解析... 很公平,我的建议可能不太可行【参考方案4】:** 编辑:哎呀,读完了 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 并查看它是如何构建的。
问候格特-扬
【讨论】:
以上是关于Lambda 表达式以及如何组合它们?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 Invoke 方法的情况下组合两个 lambda 表达式?
Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)