我有一个数字列表,我想删除所有偶数。我认为我的代码是对的:
System.Collections.Generic.List<int> list = ...
foreach (int i in list)
{
if (i % 2 == 0)
list.Remove(i);
}
但是当我运行它时,我得到一个例外。我做错了什么?
答案 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();