如果我使用:
var strings = new List<string> { "sample" };
foreach (string s in strings)
{
Console.WriteLine(s);
strings.Add(s + "!");
}
Run Code Online (Sandbox Code Playgroud)
在Add
在foreach
引发InvalidOperationException(集合被修改;枚举操作可能不会执行),我认为合理的,因为我们从我们脚下拉地毯.
但是,如果我使用:
var strings = new List<string> { "sample" };
strings.ForEach(s =>
{
Console.WriteLine(s);
strings.Add(s + "!");
});
Run Code Online (Sandbox Code Playgroud)
它通过循环迅速射入脚中直到它抛出OutOfMemoryException.
这对我来说是一个惊喜,因为我一直认为List.ForEach只是一个包装foreach
或for for
.
有没有人对这种行为的方式和原因有解释?
(通过FOREach 循环获取无限重复的通用列表)
Tho*_*que 68
这是因为该ForEach
方法不使用枚举器,它循环遍历项for
:
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]);
}
}
Run Code Online (Sandbox Code Playgroud)
(使用JustDecompile获得的代码)
由于未使用枚举器,因此它永远不会检查列表是否已更改,并且for
永远不会达到循环的结束条件,因为_size
在每次迭代时都会增加.
因为附加到List类的ForEach在内部使用直接连接到其内部成员的for循环 - 您可以通过下载.NET框架的源代码来查看.
http://referencesource.microsoft.com/netframework.aspx
其中foreach循环首先是编译器优化,但也必须作为观察者对集合进行操作 - 因此,如果集合被修改,则抛出异常.
归档时间: |
|
查看次数: |
2478 次 |
最近记录: |