为什么枚举通过集合抛出异常但循环遍历其项目却不会

ade*_*825 4 .net c# synchronization list enumerators

我正在测试一些同步结构,我注意到一些困扰我的东西.当我在同时写入一个集合时枚举它时,它抛出了异常(这是预期的),但是当我使用for循环遍历集合时,它没有.有人可以解释一下吗?我认为List不允许读者和作者同时操作.我希望循环遍历集合以展示与使用枚举器相同的行为.

更新:这是一个纯粹的学术练习.我强调,如果列表同时写入列表是很糟糕的.我也明白我需要一个同步结构.我的问题是关于为什么一个操作会像预期的那样抛出一个异常,而另一个却没有.

代码如下:

   class Program
   {
    private static List<string> _collection = new List<string>();
    static void Main(string[] args)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(AddItems), null);
        System.Threading.Thread.Sleep(5000);
        ThreadPool.QueueUserWorkItem(new WaitCallback(DisplayItems), null);
        Console.ReadLine();
    }

    public static void AddItems(object state_)
    {
        for (int i = 1; i <= 50; i++)
        {
            _collection.Add(i.ToString());
            Console.WriteLine("Adding " + i);
            System.Threading.Thread.Sleep(150);
        }
    }

    public static void DisplayItems(object state_)
    {
        // This will not throw an exception
        //for (int i = 0; i < _collection.Count; i++)
        //{
        //    Console.WriteLine("Reading " + _collection[i]);
        //    System.Threading.Thread.Sleep(150);
        //}

        // This will throw an exception
        List<string>.Enumerator enumerator = _collection.GetEnumerator();
        while (enumerator.MoveNext())
        {
            string value = enumerator.Current;
            System.Threading.Thread.Sleep(150);
            Console.WriteLine("Reading " + value);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*ell 15

枚举时不能修改集合.即使没有考虑线程问题,该规则也存在.来自MSDN:

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

基于整数的for循环实际上不是枚举器.在大多数情况下,完成同样的事情.但是,IEnumerator的接口保证您可以遍历整个集合.如果在修改集合后发生对MoveNext的调用,则平台会通过抛出异常来内部强制执行此操作.枚举器对象抛出此异常.

基于整数的for循环仅通过其数字列表.当您按整数索引集合时,您只是将项目放在该位置.如果已从列表中插入或删除某些内容,您可以跳过某个项目或两次运行相同的项目.当您需要在遍历集合时修改集合时,这在某些情况下非常有用.for循环没有枚举器对象来保证IEnumerator契约,因此不会抛出异常.