Linq Collection会在foreach的下一次迭代中重置

时间:2011-08-24 06:34:19

标签: c# .net linq c#-4.0

我有以下foreach表达式,我在其中构建谓词,然后通过执行.Where()过滤集合。

但令我感到困惑的是,即使在下一次迭代中执行result.Count()之前,0也会给我.Where()

var result = SourceCollection;

foreach (var fieldName in FilterKeys)
{
    if (!conditions.ContainsKey(fieldName)) continue;
    if (!conditions[fieldName].IsNotNullOrEmpty()) continue;
    var param = conditions[fieldName];
    Func<BaseEntity, bool> predicate = (d) => fieldName != null && d.GetFieldValue(fieldName).ContainsIgnoreCase(param);
    result =  result.Where(predicate);
}

是否有人知道我可能忽略的导致这种情况的任何LINQ行为?

2 个答案:

答案 0 :(得分:6)

我想,你想要这个:

var result = SourceCollection;

foreach (var fieldName in FilterKeys)
{
    if (!conditions.ContainsKey(fieldName)) continue;
    if (!conditions[fieldName].IsNotNullOrEmpty()) continue;
    var param = conditions[fieldName];
    var f = fieldName
    Func<BaseEntity, bool> predicate = (d) => f != null && d.GetFieldValue(f).ContainsIgnoreCase(param);
    result =  result.Where(predicate);
}

注意在谓词中使用f。您不想捕获foreach变量。在原始代码中,当第二次迭代开始时,param仍然是第一次迭代中捕获的值,但fieldName已更改。

答案 1 :(得分:3)

我同意这个问题来自于没有捕获foreach变量,但是存在更深层次的问题,那就是LINQ与命令式控制流结构的结合 - 即混合LINQ&amp;首先是foreach

请改为尝试:

var predicates =
    from fieldName in FilterKeys
    where conditions.ContainsKey(fieldName)
    let param = conditions[fieldName]
    where param.IsNotNullOrEmpty()
    select (Func<BaseEntity, bool>)
        (d => fieldName != null
              && d.GetFieldValue(fieldName).ContainsIgnoreCase(param));

var result = predicates.Aggregate(
    SourceCollection as IEnumerable<BaseEntity>,
    (xs, p) => xs.Where(p));

不需要foreach循环,代码完全保留在LINQ中。朋友不应该让朋友混合命令和功能...: - )