【问题标题】:why does it not iterate all the elements of the IEnumerable?为什么它不迭代 IEnumerable 的所有元素?
【发布时间】:2014-11-10 15:36:17
【问题描述】:

我有这个代码:

public static void myMethodMytype paramObject, IEnumerable<MyType> paramObjects)
{

    IEnumerable<Mytype> ieFilteredObjects = paramObjects.Where(x=>x.IDType == paramObject.IDType);

    if (ieFilteredObjects.Count() == 2)
    {
        foreach (MyType iterator in ieFilteredObjects)
        {
            iterator.MyProperty = null;
        }
    }
}

本例中ieFilteredObjects有2个元素,但在foreach中,只更新第一个元素,而foreach的退出。

如果我在 foreach 中使用这个:

foreach (MyType iterator in ieFilteredObjects.ToList())

然后它按预期工作。

为什么我必须将 IEnumerable 转换为列表?

谢谢。

【问题讨论】:

  • 您明显不正确的代码和正确的代码在功能上应该表现相同(允许您迭代可枚举)。在我看来,失败的原因并没有显示在您提供的代码中。
  • 您的查询计数可能会在您的 Count() 方法和 foreach 内部的 GetEnumerator 之间发生变化,因为它每次迭代时都会执行 Where 子句。 paramObjects 是否在方法外发生了变异?

标签: c# foreach ienumerable


【解决方案1】:

IEnumerable 只能迭代一次。您不能在 IEnumerable 上迭代两次并且期望得到相同的值

例如,IEnumerable 可能来自 yield return 函数,每次您在 IEnumerable 上调用 GetEnumerator() 时,您都会开始对该函数的新调用,这可能会创建新值。

这不是一个常见的用例,但它确实存在。我已经在生产中遇到过这种错误。

解决方案是缓存第一次迭代的结果。一种常见的技术是使用 linq:.ToList() 创建一个 IList,您可以无限迭代

在您的代码中,您至少要迭代两次:

  • 即FilteredObjects.Count()
  • foreach(ieFilteredObjects 中的 MyType 迭代器)

【讨论】:

  • 只能迭代一次是什么意思?我一直成功地多次迭代枚举。
  • IEnumerable can only be iterated once 我不这么认为。你在哪里找到的?
  • 您通过每次检索新的IEnumerator 来迭代IEnumerable。你的答案不正确。
  • 您需要澄清的是,Linq 是惰性求值的,因此如果底层集合在迭代之间发生更改,则多次迭代可能会产生不同的结果,而不是说它只能迭代一次。
猜你喜欢
  • 2020-12-16
  • 1970-01-01
  • 2023-02-22
  • 2019-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多