为什么列表< T> .ForEach允许修改其列表? [英] Why does List<T>.ForEach allow its list to be modified?
问题描述
如果我使用:
var strings = new List<string> { "sample" };
foreach (string s in strings)
{
Console.WriteLine(s);
strings.Add(s + "!");
}
的
添加
中在的foreach
引发InvalidOperationException(集合已修改;枚举操作可能不执行),我认为合乎逻辑的,因为我们从我们脚下拉地毯
the Add
in the foreach
throws an InvalidOperationException (Collection was modified; enumeration operation may not execute), which I consider logical, since we are pulling the rug from under our feet.
不过,如果我使用:
var strings = new List<string> { "sample" };
strings.ForEach(s =>
{
Console.WriteLine(s);
strings.Add(s + "!");
});
它及时通过循环,直到它抛出一个OutOfMemoryException拍摄自己的脚。
it promptly shoots itself in the foot by looping until it throws an OutOfMemoryException.
这是作为一个惊喜给我,因为我一直认为List.ForEach要么只是为的foreach
或<$ C的包装$ C>为。结果
没有人有该怎么解释和此行为的,为什么?
This comes as a suprise to me, as I always thought that List.ForEach was either just a wrapper for foreach
or for for
.
Does anyone have an explanation for the how and the why of this behavior?
(通过反复 ForEach循环的泛型列表Inpired不休的)
推荐答案
这是因为的ForEach
方法不使用枚举,它通过与为
循环的项目循环:
It's because the ForEach
method doesn't use the enumerator, it loops through the items with a for
loop:
public void ForEach(Action<T> action)
{
if (action == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
for (int i = 0; i < this._size; i++)
{
action(this._items[i]);
}
}
(与JustDecompile获得的代码)
(code obtained with JustDecompile)
由于不使用枚举,它从来没有检查,如果该列表已经改变,永远达不到为
循环的结束条件因为 _size
在每次迭代增加。
Since the enumerator is not used, it never checks if the list has changed, and the end condition of the for
loop is never reached because _size
is increased at every iteration.
这篇关于为什么列表< T> .ForEach允许修改其列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!