[英]Why is this code with PredicateBuilder not working?
Why is my list not returning anything? 为什么我的清单没有退回任何东西?
class Program
{
static void Main(string[] args)
{
var list = new List<string>{ "apple" , "mango" , "chickoo", "kiwi" };
var searchWord = new List<string>{ "a" };
var predicate = PredicateBuilder.False<string>();
foreach(var word in searchWord)
{
predicate.Or(p => p.Contains(word));
}
var qry = list.Where(predicate.Compile());
foreach (var item in qry)
{
Console.WriteLine(item);
}
Console.Read();
}
}
I am using Joseph Albahari's PredicateBuilder. 我正在使用Joseph Albahari的PredicateBuilder。
You need to assign the result to your predicate
variable: 您需要将结果分配给
predicate
变量:
predicate = predicate.Or(p => p.Contains(word));
The PredicateBuilder page also emphasizes an important issue: PredicateBuilder页面还强调了一个重要问题:
The temporary variable in the loop is required to avoid the outer variable trap, where the same variable is captured for each iteration of the foreach loop.
循环中的临时变量需要避免外部变量陷阱,其中为foreach循环的每次迭代捕获相同的变量。
Thus, your code should resemble this: 因此,您的代码应该类似于:
foreach(var word in searchWord)
{
var temp = word;
predicate = predicate.Or(p => p.Contains(temp));
}
There are two issues here: 这里有两个问题:
Or
extension-method does not mutate an existing expression-tree - it returns a new one. Or
extension-method不会改变现有的表达式树 - 它会返回一个新的表达式树。 Expression-trees in general are immutable. Try: 尝试:
foreach(var word in searchWord)
{
var wordCopy = word;
predicate = predicate.Or(p => p.Contains(wordCopy));
}
Or even nicer: 甚至更好:
var predicate = searchWord.Aggregate(PredicateBuilder.False<string>(),
(predSoFar, word) => predSoFar.Or(p => p.Contains(word)));
This doesn't look right to me: 这对我来说不合适:
foreach(var word in searchWord)
{
predicate.Or(p => p.Contains(word));
}
I suspect it should be: 我怀疑它应该是:
foreach(var word in searchWord)
{
predicate = predicate.Or(p => p.Contains(word));
}
In other words, just like the rest of LINQ, PredicateBuilder
doesn't let you change the current predicate - it lets you build a new predicate based on the existing one and a new condition. 换句话说,就像LINQ的其余部分一样,
PredicateBuilder
不允许您更改当前谓词 - 它允许您基于现有谓词和新条件构建新谓词。
That's certainly what the sample code suggests, anyway... 无论如何,这肯定是示例代码所暗示的......
When you look at the complete source code for PredicateBuilder
(on the same page), that confirms it - the predicate is actually just an Expression<Func<T, bool>>
- ie an expression tree. 当您查看
PredicateBuilder
的完整源代码(在同一页面上)时,它确认了它 - 谓词实际上只是一个Expression<Func<T, bool>>
- 即表达式树。 You're not creating an instance of a PredicateBuilder
class or anything like that. 您不是要创建
PredicateBuilder
类的实例或类似的东西。 Expression trees are immutable, so the only thing Or
can do is return a new expression tree, like this: 表达式树是不可变的,所以唯一的事情
Or
可以做的是返回一个新的表达式树,就像这样:
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.