显然,有很多方法可以遍历集合。好奇是否有任何不同,或者为什么你会使用一种方式而不是另一种方式。
第一种类型:
List<string> someList = <some way to init>
foreach(string s in someList) {
<process the string>
}另一种方式:
List<string> someList = <some way to init>
someList.ForEach(delegate(string s) {
<process the string>
});我不假思索地认为,你可以指定一个可重用的委托,而不是我上面使用的匿名委托……
发布于 2008-10-22 14:50:47
两者之间有一个重要且有用的区别。
因为.ForEach使用for循环来迭代集合,所以这是有效的(编辑:.net 4.5之前的-实现更改了,它们都抛出了):
someList.ForEach(x => { if(x.RemoveMe) someList.Remove(x); }); 而foreach使用枚举器,因此这是无效的:
foreach(var item in someList)
if(item.RemoveMe) someList.Remove(item);tl;dr:不要将此代码复制到您的应用程序中!
这些示例并不是最佳实践,它们只是为了演示ForEach()和foreach之间的区别。
从for循环中的列表中删除项可能会产生副作用。对这个问题的评论中描述了最常见的一个。
通常,如果您要从列表中删除多个项目,您可能希望将确定要删除的项目与实际删除分开。它不会使您的代码保持紧凑,但它可以保证您不会遗漏任何项目。
发布于 2008-10-22 15:28:59
我们这里有一些代码(在VS2005和C#2.0中),以前的工程师在他们编写的所有代码中都使用list.ForEach( delegate(item) { foo;});而不是foreach(item in list) {foo; };。例如,用于从dataReader读取行的代码块。
我还是不知道他们为什么要这么做。
list.ForEach()的缺点是:
=>“语法来使一些精练的expressions.})“。foreach(item in list)结构允许您在需要退出迭代或循环时使用break或continue。但您不能在foreach循环中更改列表。我很惊讶地发现list.ForEach的速度稍微快一些。但这可能不是从头到尾使用它的有效理由,这将是过早的优化。如果您的应用程序使用的数据库或web服务,而不是循环控制,几乎总是将是时间的去处。您是否也将其与for循环进行了基准测试?由于在内部使用了包装器,list.ForEach可能会更快,而没有包装器的for循环会更快。
我不同意list.ForEach(delegate)版本在任何重要方面都“功能更强大”的说法。它确实将一个函数传递给一个函数,但在结果或程序组织上没有太大的区别。
我不认为foreach(item in list)“确切地说出了你想要怎么做”-- for(int 1 = 0; i < count; i++)循环做到了这一点,foreach循环把控制权的选择留给了编译器。
我的感觉是,在一个新的项目中,为了遵守通用用法和可读性,对大多数循环使用foreach(item in list),并且只对较短的块使用list.Foreach(),当你可以使用C# 3 "=>“运算符做一些更优雅或紧凑的事情时。在这种情况下,可能已经有了比ForEach()更具体的LINQ扩展方法。看看Where()、Select()、Any()、All()、Max()或其他LINQ方法是否还没有从循环中执行您想要的操作。
发布于 2008-10-22 14:53:48
为了好玩,我将List弹出到reflector中,这是结果C#:
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]);
}
}类似地,foreach使用的枚举器中的MoveNext如下:
public bool MoveNext()
{
if (this.version != this.list._version)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
if (this.index < this.list._size)
{
this.current = this.list._items[this.index];
this.index++;
return true;
}
this.index = this.list._size + 1;
this.current = default(T);
return false;
}与MoveNext相比,List.ForEach的裁剪要少得多--处理更少--更有可能是把它变成高效的东西。
此外,foreach()无论如何都会分配一个新的枚举数。GC是您的朋友,但如果您重复执行相同的foreach,这将产生更多的一次性对象,而不是重用相同的委托-但-这真的是一个边缘情况。在典型的用法中,您将看到很少的差别或没有差别。
https://stackoverflow.com/questions/225937
复制相似问题