从性能的角度来看,你应该使用什么“嵌套的foreach”或"lambda/linq查询“?
发布于 2009-06-25 14:27:28
尽可能编写最清晰的代码,然后进行基准测试和性能分析,以发现任何性能问题。如果您确实有性能问题,您可以尝试不同的代码,以确定它是否更快(始终使用尽可能真实的数据进行测量),然后判断性能的提高是否值得为可读性付出代价。
在许多情况下,直接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);
}现在有两个where子句和一个select子句,所以每个最终的项目都必须通过三个迭代器。(很明显,在这种情况下,两个where子句可以组合在一起,但我要说明一个概括性的观点。)
现在将其与直接代码进行比较:
foreach (var element in list)
{
if (element.X > 2 && element.Y < 2)
{
Console.WriteLine(element.X + element.Y);
}
}这将运行得更快,因为它需要运行的环更少。不过,控制台的输出可能会使迭代器的开销相形见绌,我当然更喜欢LINQ查询。
编辑:回答“嵌套的foreach”循环...通常用SelectMany或第二个from子句表示:
var query = from item in firstSequence
from nestedItem in item.NestedItems
select item.BaseCount + nestedItem.NestedCount;这里我们只添加了一个额外的迭代器,因为由于嵌套的foreach循环,我们已经在第一个序列中为每个项目使用了一个额外的迭代器。仍然有一些开销,包括在委托中进行投影而不是“内联”的开销(我之前没有提到过),但它仍然与嵌套的foreach性能没有太大区别。
当然,这并不是说你不能用LINQ搬起石头砸自己的脚。如果你不首先使用你的大脑,你可以写出效率极低的查询--但这并不是LINQ独有的……
发布于 2009-06-25 14:31:09
如果你这样做了
foreach(Customer c in Customer)
{
foreach(Order o in Orders)
{
//do something with c and o
}
}您将执行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
}您将执行Customer.Count + Order.Count迭代,因为Enumerable.Join是作为HashJoin实现的。
发布于 2009-06-25 14:29:02
在这一点上要复杂得多。最终,大部分LINQ-to-Objects都是一个foreach循环(在幕后),但是增加了一些抽象/迭代器块/等等的开销。然而,除非你在两个版本(foreach vs LINQ)中做了非常不同的事情,否则它们都应该是O(N)。
真正的问题是:有没有一种更好的方法来编写特定于的算法,这意味着foreach将是低效的?LINQ能为你做到这一点吗?
例如,LINQ使得对数据进行散列/分组/排序变得很容易。
https://stackoverflow.com/questions/1044236
复制相似问题