list.remove()偶数的例外情况

时间:2011-12-15 23:21:33

标签: c#

我有一个数字列表,我想删除所有偶数。我认为我的代码是对的:

System.Collections.Generic.List<int> list = ...
foreach (int i in list)
{
  if (i % 2 == 0)
    list.Remove(i);
}

但是当我运行它时,我得到一个例外。我做错了什么?

7 个答案:

答案 0 :(得分:10)

你不能修改foreach循环中的集合,也就是说, 您无法从list中删除正在foreach循环中迭代的项目。

而不是foreach循环,只需使用这一行代码:

list.RemoveAll(i => i % 2 == 0);

答案 1 :(得分:2)

foreach使用了IEnumerator,当列表中的元素被删除时,它会使枚举数处于可能不一致的状态。它最“安全”的做法是抛出异常。

要解决此问题,请先制作收藏品的本地副本:

var local = new List<int>(list);
foreach (int i in local) { if (i % 2 == 0) list.Remove(i); }

答案 2 :(得分:2)

您无法在foreach循环期间修改集合。 foreach循环使用枚举器循环遍历集合,当集合被修改时,这就是枚举器发生的事情:

  

只要收集仍然存在,枚举器仍然有效   不变。如果对集合进行了更改,例如添加,   修改或删除元素,枚举器是不可恢复的   无效,其行为未定义。

您可以使用常规for循环。

for (int i = 0; i < list.Count; i++)
{
    int n = list[i];
    if (n % 2 == 0)
    {
        list.RemoveAt(i--);
    }
}

答案 3 :(得分:1)

你可以尝试这样的事情。 (它创建了一个仅包含偶数数字的新列表,而不是从现有列表中删除赔率,因此这取决于您要查看的内容。)

var numbers = Enumerable.Range(1, 100);
var evens = numbers.Where(n => n % 2 == 1);

答案 4 :(得分:1)

如果您尝试更改列表中的项目,它解释了您获得例外的原因,那么您foreach循环的所有内容都是readonly。 本文右here解释了原因。 你总是可以切换到for循环。

  for  (int i = 1 ; i < list.lenght; i++)
  {
    if (i % 2 == 0)
    list.Remove(i);

  }

答案 5 :(得分:1)

如果要从任何列表中删除(甚至是数组),则应该向后迭代它,因为删除项目会将所有项目向下移动一个位置。向前迭代将使您每次都跳过下一个项目。

你得到了哪个例外?有时,foreach会将项目锁定在foreach中使用时无法编辑的位置。相反,使用(并向后退!)

for(int i = list.Length - 1 ; i > -1 ; i--)

答案 6 :(得分:1)

遵循@Chris Filstow的方法....

这将获取您的列表,并将其替换为元素符合您标准的新列表:

System.Collections.Generic.List<int> list = ...
list = list.Where( n=> n % 2 == 0 ).ToList();