Rob*_*ler 6 c# linq ienumerable predicatebuilder
我在使用Microsoft App Studio创建的项目中的一个名为Filter.cs的文件中找到了以下代码.虽然我是一名资深的C#程序员,但我缺乏LINQ谓词表达式构建器的经验.我可以告诉它下面的代码是"元逻辑",用于灵活地构建查询,给出包含类型字段信息的过滤谓词列表以及要注入子表达式的一组数据值.我无法弄清楚的是以下语句中的"表达式"变量:
query = query.Where(expression).AsQueryable()"
Run Code Online (Sandbox Code Playgroud)
..将每个字段的表达式连接成一个更复杂的查询表达式,最终在代码的末尾执行以创建ObservableCollection 结果.如果它是" query + = "我可以推断链接动作就像一个事件处理程序字段,但作为一个直接的赋值语句,它让我感到困惑,因为我希望它能替换表达式变量从最后一个循环迭代得到的最后一个值,从而在过程中重置它并丢失其先前的值.这里发生了什么?
public class Filter<T>
{
public static ObservableCollection<T> FilterCollection(
FilterSpecification filter, IEnumerable<T> data)
{
IQueryable<T> query = data.AsQueryable();
foreach (var predicate in filter.Predicates)
{
Func<T, bool> expression;
var predicateAux = predicate;
switch (predicate.Operator)
{
case ColumnOperatorEnum.Contains:
expression = x => predicateAux.GetFieldValue(x).ToLower().Contains(predicateAux.Value.ToString().ToLower());
break;
case ColumnOperatorEnum.StartsWith:
expression = x => predicateAux.GetFieldValue(x).ToLower().StartsWith(predicateAux.Value.ToString().ToLower());
break;
case ColumnOperatorEnum.GreaterThan:
expression = x => String.Compare(predicateAux.GetFieldValue(x).ToLower(), predicateAux.Value.ToString().ToLower(), StringComparison.Ordinal) > 0;
break;
case ColumnOperatorEnum.LessThan:
expression = x => String.Compare(predicateAux.GetFieldValue(x).ToLower(), predicateAux.Value.ToString().ToLower(), StringComparison.Ordinal) < 0;
break;
case ColumnOperatorEnum.NotEquals:
expression = x => !predicateAux.GetFieldValue(x).Equals(predicateAux.Value.ToString(), StringComparison.InvariantCultureIgnoreCase);
break;
default:
expression = x => predicateAux.GetFieldValue(x).Equals(predicateAux.Value.ToString(), StringComparison.InvariantCultureIgnoreCase);
break;
}
// Why doesn't this assignment wipe out the expression function value from the last loop iteration?
query = query.Where(expression).AsQueryable();
}
return new ObservableCollection<T>(query);
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,您无法理解为什么这一行在循环中执行
query = query.Where(expression).AsQueryable();
Run Code Online (Sandbox Code Playgroud)
产生类似于表达式“串联”的效果。一个简短的答案是,这与为什么相似
str = str + suffix;
Run Code Online (Sandbox Code Playgroud)
产生一个更长的字符串,即使它是一个赋值。
更长的答案是循环一次构建一个谓词一个表达式,并将 a 附加Where到条件序列中。尽管它是一个赋值,但它是根据对象的先前状态构建的,因此先前的表达式不会“丢失”,因为它被用作更大、更复杂的过滤表达式的基础。
为了更好地理解它,想象一下该switch语句生成的各个表达式被放入一个IQueryable对象数组中,而不是附加到query. 一旦构建了零件数组,您就可以执行以下操作:
var query = data.AsQueryable()
.Where(parts[0]).AsQueryable()
.Where(parts[1]).AsQueryable()
...
.Where(parts[N]).AsQueryable();
Run Code Online (Sandbox Code Playgroud)
现在观察每个parts[i]仅使用一次;之后,就不再需要它了。这就是为什么您可以在循环中增量构建表达式链:在第一次迭代之后,query包含一个包含第一项的链;在第二次迭代之后,它包含两个第一项,依此类推。