Lyi*_*Sky 102 c# collections
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;
}
Run Code Online (Sandbox Code Playgroud)
如果你注释掉内部for
循环,它会抛出,显然是因为我们对集合进行了更改.
现在,如果你取消注释,为什么这个循环允许我们添加这两个项目?它需要一段时间才能运行半分钟(在奔腾CPU上),但它不会抛出,而有趣的是它输出:
这有点预期,但它表明我们可以改变,它实际上改变了收藏.任何想法为什么会发生这种行为?
Jon*_*eet 119
问题在于List<T>
检测修改的方法是保留类型的版本字段,int
在每次修改时递增它.因此,如果你做了准确的2次某个倍数32修改,迭代之间的列表,它会尽可能的检测而言渲染无形的这些修改.(它将从溢出int.MaxValue
来int.MinValue
,并最终回到其初始值.)
如果你几乎改变了你的代码 - 添加1或3个值而不是2,或者将内循环的迭代次数减少1,那么它将按预期抛出异常.
(这是一个实现细节,而不是指定的行为 - 它是一个实现细节,可以在非常罕见的情况下被视为一个错误.但是,看到它在真实程序中导致问题是非常不寻常的.)