【问题标题】:foreach loop vs. ForEach method - Differences? [duplicate]foreach 循环与 ForEach 方法 - 区别? [复制]
【发布时间】:2016-02-02 12:36:30
【问题描述】:

编辑:这个问题可以标记为this question.的重复项

使用 foreach 循环或 ForEach LINQ 方法之间是否有任何差异(性能或其他方面)?

对于上下文,这是我的一种方法的一部分:

foreach (var property in typeof(Person).GetProperties())
{
    Validate(property.Name);
}

我也可以使用此代码执行相同的任务:

typeof(Person)
    .GetProperties()
    .ToList()
    .ForEach(property => Validate(property.Name));

什么时候使用循环结构比使用方法链接更好?

这是我使用ForEach 方法的另一个示例,但可以轻松地使用 foreach 循环和变量:

// LINQ
PrivateData.Database.Users
           .Cast<User>()
           .Where(user => user.LoginType == LoginType.WindowsUser)
           .Select(user => new { Name = user.Name, Login = user.Login })
           .ToList()
           .ForEach(result => WriteObject(result));

// Loop
var users = PrivateData.Database.Users
               .Cast<User>()
               .Where(user => user.LoginType == LoginType.WindowsUser)
               .Select(user => new { Name = user.Name, Login = user.Login });

foreach(var user in users)
{
    WriteObject(user);
}

【问题讨论】:

  • 请注意,您必须先调用ToList,然后才能以LINQ 样式使用ForEach - 迭代某些内容并执行这样的操作并不是真正的“LINQy”做事方式.
  • @Thomas LINQ 没有ForEach 方法。正确的 LINQ 方法是使用 foreach 循环。
  • 有什么方法可以更快地查看您携带的金额? 1:打开你的钱包,看看账单。 2:买一个新的钱包,把账单复印一下,放到新的钱包里,然后看看复印件。在软件工程术语中:您使用 ToList() 只是为了使用 ForEach 会产生 O(n) 存储成本。 .NET 和现代机器使存储变得便宜,它不是免费的。
  • @Noel 1. 大概方法是void,所以这不会是有效的 2. 这意味着查询永远不会被迭代,因此方法永远不会运行。
  • Eric Lippert 有一篇关于此blogs.msdn.com/b/ericlippert/archive/2009/05/18/…的精彩博文

标签: c# linq foreach


【解决方案1】:

我会把你推迟到Eric Lipperts blog "foreach" vs "ForEach"。作为之前C# 编译器团队的主要开发人员,我认为他的意见是正确的。

摘录:(参考.ForEach()

第一个原因是这样做违反了所有其他序列运算符所基于的函数式编程原则。显然调用此方法的唯一目的是引起副作用。表达式的目的是计算一个值,而不是产生副作用。声明的目的是产生副作用。这个东西的调用点看起来很像一个表达式(虽然,诚然,由于该方法是返回无效的,所以该表达式只能在“语句表达式”上下文中使用。)它不适合我制作唯一一个仅对其副作用有用的序列运算符。

【讨论】:

    【解决方案2】:

    在大多数情况下,这是个人喜好问题。谈论性能:

    大多数时候,LINQ 会有点慢,因为它会引入开销。如果您非常关心性能,请不要使用 LINQ。使用 LINQ 是因为您想要更短、更易读、更易于维护的代码。

    【讨论】:

    • ForEach 不是 LINQ。
    • 这个答案可以通过指定 LINQ 引入的指定开销以及在什么情况下包含开销来改进。
    【解决方案3】:

    循环是更好的样式,因为它是一个完全为您想要做的事情而制作的工具。它与语言更好地集成。例如,您可以从循环中中断。工具理解循环,他们不理解ForEach

    对于人类来说,循环也更容易理解。 ForEach 非常少见。

    循环也更快,因为间接调用更少,委托分配更少,优化器可以在一个地方看到更多你正在做的事情。它还保存了ToList 调用。您也可以通过在 IEnumerable&lt;T&gt; 上编写自定义扩展方法来保存该调用。

    我认为循环在我能想到的所有情况下都优越。也许在某些极端情况下,ForEach 方法由于某种原因会更好或更方便。

    PLINQ 还有一个ForAll,出于效率原因,它是必需的,因为它可以并行化。

    【讨论】:

    • "less delegate allocations" 代表将被编译为一个方法,它不会,这意味着它与具有普通方法调用的foreach 没有什么不同。唯一的区别是.ToList(),正如你所说,可以通过自定义扩展方法来解决......
    • @Phill lambda 将被编译成一个方法。然后在构造传递给该方法的新分配委托时使用该方法。
    • 我并没有真正遵循,因为他的示例也可以写成:.ForEach(WriteObject),它应该编译成我认为大致相同的 IL 代码。 (如果我完成了我正在做的事情,我可能会出于好奇很快尝试这个)
    • @Phill 该代码确实需要分配一个委托,你是完全正确的。这就是为什么 foreachForEach 之间的区别,与使用 lambda 无关。
    • 投反对票,因为它主要是关于个人偏好的意见答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 2013-06-09
    • 2015-05-19
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多