"嵌套foreach"vs"lambda/linq查询"性能(LINQ-to-Objects)

JSC*_*JSC 37 c# foreach lambda linq-to-objects

从性能的角度来看,你应该使用"嵌套的foreach"或"lambda/linq查询"?

Jon*_*eet 59

尽可能编写最清晰的代码,然后进行基准测试和配置文件以发现任何性能问题.如果您确实遇到了性能问题,可以尝试使用不同的代码来确定它是否更快(尽可能使用尽可能真实的数据进行测量),然后判断性能的提高是否值得提高可读性击中.

一个直接foreach的办法在许多情况下比LINQ更快.例如,考虑:

var query = from element in list
            where element.X > 2
            where element.Y < 2
            select element.X + element.Y;

foreach (var value in query)
{
    Console.WriteLine(value);
}
Run Code Online (Sandbox Code Playgroud)

现在有两个where子句和一个select子句,所以每个最终的项都必须通过三个迭代器.(显然,在这种情况下,两个where子句可以合并,但我总的来说.)

现在将它与直接代码进行比较:

foreach (var element in list)
{
    if (element.X > 2 && element.Y < 2)
    {
        Console.WriteLine(element.X + element.Y);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将运行得更快,因为它可以运行更少的篮球.有可能控制台输出会使迭代器成本相形见绌,我当然更喜欢LINQ查询.

编辑:回答"嵌套的foreach"循环...通常用SelectMany或表示第二个from子句:

var query = from item in firstSequence
            from nestedItem in item.NestedItems
            select item.BaseCount + nestedItem.NestedCount;
Run Code Online (Sandbox Code Playgroud)

这里我们只添加一个额外的迭代器,因为我们已经在第一个序列中使用了一个额外的迭代器,因为嵌套foreach循环.还有一些开销,包括在委托中进行投影而不是"内联"(我之前没有提到过)的开销,但它仍然与嵌套的foreach性能没有太大差别.

当然,这并不是说你不能用LINQ射击自己.如果你不首先吸引你的大脑,你可以编写极其低效的查询 - 但这远非LINQ独有的......

  • 第一句应该打印成横幅并挂在每个编程部门. (13认同)

Amy*_*y B 23

如果你这样做

foreach(Customer c in Customer)
{
  foreach(Order o in Orders)
  {
    //do something with c and o
  }
}
Run Code Online (Sandbox Code Playgroud)

您将执行Customer.Count*Order.Count迭代


如果你这样做

var query =
  from c in Customer
  join o in Orders on c.CustomerID equals o.CustomerID
  select new {c, o}

foreach(var x in query)
{
  //do something with x.c and x.o
}
Run Code Online (Sandbox Code Playgroud)

您将执行Customer.Count + Order.Count迭代,因为Enumerable.Join是作为HashJoin实现的.

  • 那是因为你运行了两种不同的算法; 你在比较苹果和橘子.我不明白这与提出的问题有什么关系. (5认同)
  • 您的嵌套foreach实际上等同于SelectMany,而不是Join - 即来自客户中的c来自订单中的o ...(无加入) (4认同)
  • 给予好评!@mquander:OP不太可能"if(c.CustomerID!= o.CustomerID)继续;" 作为循环内的第一个语句. (2认同)

Mar*_*ell 11

它更复杂.最终,LINQ-to-Objects的大部分是(幕后)一个foreach循环,但是增加了一些抽象/迭代器块等的开销.但是,除非你在两个版本中做了非常不同的事情(foreach vs LINQ) ,他们都应该是O(N).

真正的问题是:有没有更好的方法来编写您的特定算法,这意味着foreach效率低下?LINQ可以帮你吗?

例如,LINQ可以轻松地对数据进行散列/分组/排序.