当前位置:  开发笔记 > 编程语言 > 正文

迭代通过枚举器时的集合

如何解决《迭代通过枚举器时的集合》经验,为你挑选了2个好方法。

运行此代码时:

var list = new List
{
    "foo",
    "bar",
};

foreach (var l in list)
{
    Console.WriteLine(l);

    list.Add("bar");
}

抛出异常:

System.InvalidOperationException:集合已被修改; 枚举操作可能无法执行.

当枚举器迭代该集合时,.NET如何知道集合被修改?在集合对象中是否有这样的标志?



1> CodeCaster..:

A List在整数变量中内部保存其"版本".对列表的每次修改(添加,删除,排序,清除......)都会将此版本增加一个.

现在,a的枚举器List在初始化时会保存此版本号.在每次MoveNext()迭代时,即在每次迭代时,它检查列表的版本号是否仍然等于保存的版本号.

这样,它可以检测何时在两次迭代之间修改列表.请注意,此实现会导致整数溢出的特殊错误:为什么此代码会抛出"Collection was modified",但是当我在它之前迭代某些东西时,它不会?.

似乎还有一个错误Sort(Comparison comparison),它不会增加版本号.这段代码:

var list = new List
{
    "foo",
    "bar",
};

foreach (var l in list)
{
    Console.WriteLine(l);
    list.Sort((x, y) => x.CompareTo(y));
}

打印:

foo
foo



2> Dmitry Byche..:

是的,典型的解决方案是标志,版本值等,例如,如果是 List

https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,cf7f4095e4de7646

这是一个版本

 private int _version;

例如

 public bool MoveNext() {
   ...
   return MoveNextRare()
 } 

 private bool MoveNextRare()
 {                
   if (version != list._version) {
     ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
 }

推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有