为什么我可以更改foreach()中的数组元素,但不能更改列表元素?

时间:2015-02-06 10:07:13

标签: c#

class Program
{
    static void Main()
    {
        int[] arr = new int[5]{ 1,2,3,4,5};
        List<int> list = new List<int>() { 1,2,3,4,5};
        foreach(int i in arr)
        {
            arr[2] = 7;
            Console.WriteLine(i);
        }
        Console.WriteLine();

        foreach (int i in list)
        {
            list[2] = 7;
            Console.WriteLine(i);
        }
        Console.ReadKey();
    }

在集合上使用foreach()将获得一个枚举器并重复调用MoveNext()

对于数组,我可以在迭代时更改集合中的项目。

然而,迭代List<T>的代码在第一个循环之后引发异常:

  

收藏被修改;枚举操作可能无法执行。

为什么允许使用数组,但不允许使用List<T>

1 个答案:

答案 0 :(得分:2)

List<T>保留version变量,该变量随每次修改而变化。添加,删除或更改列表中的项目会增加版本。

当创建列表的枚举器时,它将被绑定到当时列表的版本。每次调用MoveNext()(或:每次foreach()次迭代)时,都会根据原始列表检查此版本。当版本不同时,抛出给定的异常。

ArrayEnumerator没有这样的检查,因为数组实际上没有版本字段。但是,MSDN mentions at Array.GetEnumerator()

  

只要集合保持不变,枚举器仍然有效。如果对集合进行了更改(例如添加,修改或删除元素),则枚举数将无法恢复,其行为未定义

因此,虽然您的第一个示例似乎正在起作用,但并不能保证。