显然有许多方法可以迭代集合。很好奇是否有什么不同,或者为什么你用一种方式而不是另一种。

第一类型:

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>
});

我想,除了我上面使用的匿名委托,你还可以指定一个可重用的委托。


当前回答

您展示的第二种方法使用扩展方法为列表中的每个元素执行委托方法。

这样,您就有了另一个委托(=方法)调用。

此外,还可以使用for循环迭代列表。

其他回答

我猜somlist . foreach()调用可以很容易地并行化,而正常的foreach不那么容易并行运行。 您可以很容易地在不同的核心上运行几个不同的委托,这对于普通的foreach来说并不容易做到。 这只是我的小意思

你可以命名匿名委托:-)

你可以把第二个写成

someList.ForEach(s => s.ToUpper())

我更喜欢这个,而且节省了很多打字。

正如Joachim所说,并行性更容易应用于第二种形式。

List.ForEach()被认为更具功能性。

List.ForEach()表示你想做什么。Foreach(列表中的项目)也确切地说明了你想要如何完成它。这就剩下List了。ForEach可以自由更改未来如何部分的实现。例如,一个假设的。net未来版本可能总是运行List。在并行的情况下,假设此时每个人都有一些cpu核心通常处于空闲状态。

另一方面,foreach (list中的项)让您对循环有更多的控制。例如,您知道项目将以某种顺序进行迭代,如果项目满足某些条件,则很容易在中间中断。


关于这个问题的一些最新评论可在此查阅:

https://stackoverflow.com/a/529197/3043

我知道有两件事让他们不一样。去我!

首先,有一个典型的错误,即为列表中的每个项目创建一个委托。如果你使用foreach关键字,你所有的委托最终都会指向列表的最后一项:

    // A list of actions to execute later
    List<Action> actions = new List<Action>();

    // Numbers 0 to 9
    List<int> numbers = Enumerable.Range(0, 10).ToList();

    // Store an action that prints each number (WRONG!)
    foreach (int number in numbers)
        actions.Add(() => Console.WriteLine(number));

    // Run the actions, we actually print 10 copies of "9"
    foreach (Action action in actions)
        action();

    // So try again
    actions.Clear();

    // Store an action that prints each number (RIGHT!)
    numbers.ForEach(number =>
        actions.Add(() => Console.WriteLine(number)));

    // Run the actions
    foreach (Action action in actions)
        action();

列表中。每个方法都没有这个问题。迭代的当前项按值作为参数传递给外部lambda,然后内部lambda在自己的闭包中正确地捕获该参数。问题解决了。

(遗憾的是,我认为ForEach是List的成员,而不是扩展方法,尽管很容易自己定义它,因此您可以在任何可枚举类型上使用此功能。)

其次,ForEach方法有一定的局限性。如果你通过使用yield return来实现IEnumerable,你不能在lambda中做yield return。因此,通过循环遍历集合中的项以获得返回值是不可能的。您必须使用foreach关键字,并通过手动在循环中复制当前循环值来解决闭包问题。

更多的在这里

在幕后,匿名委托被转换为一个实际的方法,因此如果编译器没有选择内联函数,那么第二个选择可能会有一些开销。此外,匿名委托示例主体引用的任何局部变量在本质上都会发生变化,因为编译器会使用一些技巧来隐藏它被编译为新方法的事实。这里有更多关于c#如何做到这一点的信息:

http://blogs.msdn.com/oldnewthing/archive/2006/08/04/688527.aspx