为什么我的列表没有返回任何内容?
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();
}
}
我正在使用Joseph Albahari的PredicateBuilder。
答案 0 :(得分:18)
您需要将结果分配给predicate
变量:
predicate = predicate.Or(p => p.Contains(word));
PredicateBuilder page也强调了一个重要问题:
循环中的临时变量是 要求避免外部变量 陷阱,其中相同的变量是 为每次迭代捕获 foreach循环。
因此,您的代码应该类似于:
foreach(var word in searchWord)
{
var temp = word;
predicate = predicate.Or(p => p.Contains(temp));
}
答案 1 :(得分:5)
这里有两个问题:
Or
扩展方法不会改变现有的表达式树 - 它会返回一个新的表达式树。表达式树通常是不可变的。尝试:
foreach(var word in searchWord)
{
var wordCopy = word;
predicate = predicate.Or(p => p.Contains(wordCopy));
}
甚至更好:
var predicate = searchWord.Aggregate(PredicateBuilder.False<string>(),
(predSoFar, word) => predSoFar.Or(p => p.Contains(word)));
答案 2 :(得分:2)
这对我来说不合适:
foreach(var word in searchWord)
{
predicate.Or(p => p.Contains(word));
}
我怀疑它应该是:
foreach(var word in searchWord)
{
predicate = predicate.Or(p => p.Contains(word));
}
换句话说,就像LINQ的其余部分一样,PredicateBuilder
不允许您更改当前谓词 - 它可以让您构建 new 谓词基于现有的和新的条件。
这肯定是sample code所暗示的,无论如何......
当您查看PredicateBuilder
的完整源代码(在同一页面上),确认它时 - 谓词实际上只是Expression<Func<T, bool>>
- 即表达式树。您没有创建PredicateBuilder
类的实例或类似的任何内容。表达式树是不可变的,所以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);
}