• 错误信息: 集合已修改;可能无法执行枚举操作。


    错误信息:     集合已修改;可能无法执行枚举操作 

     调用堆栈:   

     在 System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)    

     在 System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()

    这个错误是怎么引发的?

    我们具体分析一下Dictionary的内部实现。

      public class Dictionary<TKey, TValue>

        {

            //字典的版本号

            private int version;

            public void Clear()

            {

                //执行这个操作后,版本号加一,版本发生变化

                this.version++;

            }

            private void Insert(TKey key, TValue value, bool add)

            {

                //执行这个操作后,版本号加一,版本发生变化

                this.version++;

            }

            public bool Remove(TKey key)

            {

                //执行这个操作后,版本号加一,版本发生变化

                this.version++;

            }

            public void Add(TKey key, TValue value)

            {

                //执行这个操作后,版本号加一,版本发生变化

                this.Insert(key, value, true);

            }

            public struct Enumerator

            {

                private Dictionary<TKey, TValue> dictionary;

                //Enumerator的版本号

                private int version;

                internal Enumerator(Dictionary<TKey, TValue> dictionary)

                {

                    this.dictionary = dictionary;

                    //初始化时,把当时dictionary.version传给Enumerator的version

                    this.version = dictionary.version;

                }

                public bool MoveNext()

                {

                    //如果dictionary.version发生变化,就会抛出上面的异常

                    if (this.version != this.dictionary.version)

                    {

                        ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);

                    }

                }

            }

    通过分析源码可以知道,只要dictionary.version发生变化,在做foreach循环时,就会抛出上面的错误。

    具体来说,在做foreach循环时,dictionary对象发生Clear、Insert、Remove、Add操作时,就会引发上面的异常。

    如果代码场景涉及到并发操作,推荐用并发字典ConcurrentDictionary,不要自己加锁控制并发。

  • 相关阅读:
    Javascript之DOM的三大节点及部分用法
    Javascript之全局变量和局部变量部分讲解
    《TCP/IP详解 卷1:协议》系列分享专栏
    说一说MySQL的锁机制
    《TCP/IP详解 卷1:协议》第3章 IP:网际协议
    PHP连接MySql闪断自动重连的方法
    关于MySQL的锁机制详解
    React 源码中的依赖注入方法
    《Mysql高级知识》系列分享专栏
    《AngularJS学习整理》系列分享专栏
  • 原文地址:https://www.cnblogs.com/50614090/p/9728750.html
Copyright © 2020-2023  润新知