list.remove()中的偶数异常
本文关键字:异常 remove list | 更新日期: 2023-09-27 18:18:13
我有一个数字列表,我想删除所有偶数。我认为我的代码是正确的:
System.Collections.Generic.List<int> list = ...
foreach (int i in list)
{
if (i % 2 == 0)
list.Remove(i);
}
但是当我运行它时,我得到一个异常。我做错了什么?
你不能在foreach
循环中修改集合,也就是说,你不能从list
中删除在foreach
循环中迭代的项。
代替foreach
循环,只使用这一行代码:
list.RemoveAll(i => i % 2 == 0);
不能在foreach
循环期间修改集合。foreach
循环使用枚举数遍历该集合,当该集合被修改时,枚举数所发生的变化如下:
只要该集合存在,枚举数就保持有效不变。如果对集合进行了更改,例如添加,修改或删除元素时,枚举数不可恢复无效,其行为未定义。
可以使用常规的for
循环。
for (int i = 0; i < list.Count; i++)
{
int n = list[i];
if (n % 2 == 0)
{
list.RemoveAt(i--);
}
}
foreach
在幕后使用IEnumerator
,当列表中的元素被删除时,它使枚举器处于潜在的不一致状态。对它来说,最安全的做法是抛出异常。
要解决这个问题,首先创建一个集合的本地副本:
var local = new List<int>(list);
foreach (int i in local) { if (i % 2 == 0) list.Remove(i); }
如果你要从列表中删除任何东西(甚至是数组),你应该向后迭代它,因为删除一个项目会将它之后的所有项目向下移动一个位置。向前迭代将导致每次都跳过下一项。
你得到了哪个异常?有时,foreach会将在foreach中使用的项锁定到无法编辑的位置。相反,使用for(并返回!)
for(int i = list.Length - 1 ; i > -1 ; i--)
遵循@Chris Filstow的方法....
这将获取您的列表,并将其替换为符合条件的新元素:
System.Collections.Generic.List<int> list = ...
list = list.Where( n=> n % 2 == 0 ).ToList();
您可以尝试这样做。(它只创建一个包含偶数的新列表,而不是从现有列表中删除奇数,所以这取决于您想要做什么。)
var numbers = Enumerable.Range(1, 100);
var evens = numbers.Where(n => n % 2 == 1);
所有你得到的foreach
循环是readonly
,如果你试图改变列表中的项目,它解释了为什么你得到一个异常。这篇文章解释了其中的原因。你可以切换到for
循环。
for (int i = 1 ; i < list.lenght; i++)
{
if (i % 2 == 0)
list.Remove(i);
}