为什么这个代码抛出“集合被修改”,但是当我迭代之前,它不是? [英] Why this code throws 'Collection was modified', but when I iterate something before it, it doesn't?

查看:88
本文介绍了为什么这个代码抛出“集合被修改”,但是当我迭代之前,它不是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  var ints = new List< int>(new [] {
1,
2,
3,
4,
5
});
var first = true;
foreach(var v in ints){
if(first){
for(long i = 0; i ints.Add(1);
ints.RemoveAt(ints.Count - 1);
}
ints.Add(6);
ints.Add(7);
}
Console.WriteLine(v);
first = false;
}

如果您注释掉 c $ c> loop,it throws,这显然是因为我们对集合做了更改。



现在如果你取消注释,为什么这个循环允许我们添加这两个项?它需要一些时间来运行它像半分钟(在奔腾CPU),但它不抛出,有趣的是,它输出:





这是一个预期,但它表明我们可以改变,它实际上改变了集合。任何想法为什么这种行为发生?

解决方案

问题是, List< T& / code>检测修改是通过保留类型 int 的版本字段,在每次修改时增加它。因此,如果您在迭代之间对列表进行了完全倍数的 32 修改,那么在检测方面,这些修改将不可见。 (它将从 int.MaxValue int.MinValue 溢出并最终恢复到其初始值。 p>

如果你改变你的代码几乎任何东西 - 添加1或3值而不是2,或者将内循环的迭代次数减少1,那么它会抛出



(这是一个实现细节而不是指定的行为 - 它是一个实现细节,在极少数情况下可以被视为一个错误非常不寻常的看到它导致一个真正的程序中的问题,但是。)


var ints = new List< int >( new[ ] {
    1,
    2,
    3,
    4,
    5
} );
var first = true;
foreach( var v in ints ) {
    if ( first ) {
        for ( long i = 0 ; i < int.MaxValue ; ++i ) { //<-- The thing I iterate
            ints.Add( 1 );
            ints.RemoveAt( ints.Count - 1 );
        }
        ints.Add( 6 );
        ints.Add( 7 );
    }
    Console.WriteLine( v );
    first = false;
}

If you comment out the inner for loop, it throws, it's obviously because we did changes to the collection.

Now if you uncomment it, why this loop allow us to add those two items? It takes awhile to run it like half a minute (On Pentium CPU), but it doesn't throw, and the funny thing is that it outputs:

It was a bit of expected, but it indicates that we can change and it actually changes the collection. Any ideas why this behaviour occuring?

解决方案

The problem is that the way that List<T> detects modifications is by keeping a version field, of type int, incrementing it on each modification. Therefore, if you've made exactly some multiple of 232 modifications to the list between iterations, it will render those modifications invisible as far as detection is concerned. (It will overflow from int.MaxValue to int.MinValue and eventually get back to its initial value.)

If you change pretty much anything about your code - add 1 or 3 values rather than 2, or lower the number of iterations of your inner loop by 1, then it will throw an exception as expected.

(This is an implementation detail rather than specified behaviour - and it's an implementation detail which can be observed as a bug in a very rare case. It would be very unusual to see it cause a problem in a real program, however.)

这篇关于为什么这个代码抛出“集合被修改”,但是当我迭代之前,它不是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆