循环语句和List类的ForEach()方法

26 浏览
0 Comments

循环语句和List类的ForEach()方法

显然有许多方法可以迭代一个集合。好奇有什么区别,或者为什么会使用一种方法而不是另一种方法。

第一种类型:

List someList = 
foreach(string s in someList) {
   
}

另一种方法:

List someList = 
someList.ForEach(delegate(string s) {
    
});

我想,从我的头脑中想象,与我上面使用的匿名委托不同,你将有一个可重用的委托你可以指定...

admin 更改状态以发布 2023年5月21日
0
0 Comments

我们有一些代码(在VS2005和C#2.0中),其中先前的工程师费尽心思地使用list.ForEach(delegate(item){foo; }); 而不是 foreach(item in list){foo; };编写他们所编写的所有代码。例如,从数据读取器中读取行的代码块。

我仍然不知道他们为什么这样做。

list.ForEach()的缺点是:

它在C# 2.0中更为冗长。但是,在C#3及以后,您可以使用“=> ”语法以使一些表达式变得更加简洁。

它不太熟悉。必须维护此代码的人们会想知道为什么要那样做。我花了一段时间才确定没有任何理由,除了可能让作者显得聪明(其余代码的质量削弱了这一点)。它也不太可读,委托代码块末尾有“}) ”。

另请参见比尔·瓦格纳的书《Effective C#:50种改善C#的特定方法》,在其中他谈到为什么foreach比其他循环(如for或while循环)更受青睐的原因-主要是因为您让编译器决定构建循环的最佳方法。如果将来的编译器版本成功使用更快的技术,则使用foreach并重新构建会免费获得此功能,而不是更改代码。

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) 做大多数的循环,以符合通用用法并提高可读性,而只有在需要使用 C# 3 的 "=>" 操作符更加优雅和简洁的短小代码块时再使用 list.Foreach()。在这种情况下,可能已经有比 ForEach() 更具体的 LINQ 扩展方法实现了你想要的循环功能。可以查看一下是否已经有 Where(), Select(), Any(), All(), Max() 或许多其他 LINQ 方法实现了你所需的循环功能。

0
0 Comments

这两者之间有一个重要且有用的区别。

因为 .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);


简而言之:不要把这段代码复制粘贴到你的应用程序中!

这些示例不是最佳实践,只是为了演示 ForEach() 和 foreach 之间的区别。

在 for 循环内从列表中移除项可能会产生副作用,最常见的副作用在这个问题的评论中有描述。

一般来说,如果你想从列表中移除多个项,你会想要将确定要移除的项与实际移除分开。这不会使代码更简洁,但它保证你不会错过任何项。

0