为什么列表< T> .ForEach允许修改其列表? [英] Why does List<T>.ForEach allow its list to be modified?

查看:130
本文介绍了为什么列表< T> .ForEach允许修改其列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用:

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.

这篇关于为什么列表&LT; T&GT; .ForEach允许修改其列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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