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

发布于 2024-12-01 15:02:36 字数 652 浏览 0 评论 0原文

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

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

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 行为导致了这种情况吗?

I have the following foreach expression within which I am building a predicate and then filtering the collection by executing .Where().

But what stumps me is, result.Count() gives me 0 even before I execute .Where() in the next iteration.

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);
}

Does, anybody know of any LINQ behavior that I might have overlooked that is causing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

破晓 2024-12-08 15:02:36

我想,你想要这样:

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 已更改。

I think, you want this:

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);
}

Notice the use of f in the predicate. You don't want to capture the foreach variable. In your original code, when the second iteration starts, param is still the captured value from the first iteration, but fieldName has changed.

日记撕了你也走了 2024-12-08 15:02:36

我同意这个问题来自于没有捕获 foreach 变量,但还有一个更深层次的问题,那就是 LINQ 与命令式控制流结构的组合 - 即混合 LINQ 和 foreach 变量。首先是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 中。朋友不应该让朋友混合命令式和功能性......:-)

I agree that the issue comes from not capturing the foreach variable, but there is a deeper issue and that is the combination of LINQ with imperative control flow structures - i.e. mixing LINQ & foreach in the first place.

Try this instead:

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));

No foreach loop needed and the code stays purely in LINQ. Friends shouldn't let friends mix imperative and functional... :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文