foreach loop vs. ForEach method - Differences?
编辑:此问题可以标记为此问题的副本。
在使用foreach循环或ForEachLINQ方法之间是否存在任何差异(性能或其他方面)?
对于上下文,这是我的方法之一的一部分:
1 2 3 4
| foreach (var property in typeof(Person ).GetProperties())
{
Validate (property .Name);
} |
我也可以使用此代码执行相同的任务:
1 2 3 4
| typeof(Person )
.GetProperties()
.ToList()
.ForEach(property => Validate (property .Name)); |
什么时候使用循环结构比使用方法链接更好?
下面是另一个例子,我使用了ForEach方法,但可以很容易地使用foreach循环和变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| // 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 );
} |
- 请注意,在Linq样式中使用ForEach之前,您必须如何调用ToList--迭代某些内容并执行类似的操作,这并不是真正的"Linqy"方式。
- 根据我的经验,直线加速器的速度要慢2倍。你能做的最好的就是在释放模式下测量它。
- @Thomas Linq没有ForEach方法。正确的LINQ方法是使用ForEach循环。
- foreach是列表中的一种方法,因此它需要一个额外的.ToList(),从而减慢所有操作的速度并消耗额外的内存。或者,可以在IEnumerable上实现自己的foreach扩展方法,这样就不必运行.ToList()。我个人更喜欢扩展,但正如詹姆斯指出的那样,这是一种不那么简单的方法。
- 也许您只是举了一个例子,但是如果您不需要这些语句后的结果,您可以通过在Select中调用WriteObject来简化这两个例子。
- 检查你带了多少钱的更快方法是什么?1:打开钱包,看看钞票。2:买一个新钱包,复印账单,放进新钱包,然后看复印件。在软件工程术语中:您使用tolist()只是为了使用foreach而增加了O(n)存储成本。.net和现代机器使存储变得便宜,这不是免费的。
- 诺尔1。假设方法是void,所以这不是有效的2。这意味着永远不会迭代查询,因此该方法也不会运行。
- @jamesthorpe,所以我最好只查询元素,然后在foreach循环中遍历它们,而不是只在一个大语句中尝试做所有事情?
- @杰克在我看来,是的。尤其是当收集是从某个地方/从数据库等读取时。
- @诺埃尔,我不认为你能用选择方法做到这一点。这是我必须尝试的。
- @杰克,你不能在Select中这样做,除非你能保证某个东西会在某个时刻迭代列表,或者你仍然会在上面调用.ToList或者类似的东西。
- @博士琼斯,去点击"标记为重复"按钮,但问题已经解决了。那条线索中最热门的答案为我解释了这一点。
- 埃里克·利珀特有一篇关于这个博客的博文。msdn.com/b/ericlippet/archive/2009/05/18/&hellip;
- 考虑数据库中的ToList,如果结果是数十亿条记录,那么在执行ForEach之前,您将耗尽内存。相反,原始查询上的ForEach将一次加载一条记录。
我会把你推迟到EricLippers的博客"foreach"和"foreach"。作为C编译器团队的前主要开发人员,我认为他的观点是正确的。
摘录:(参考.ForEach())
The first reason is that doing so violates the functional programming principles that all the other sequence operators are based upon. Clearly the sole purpose of a call to this method is to cause side effects. The purpose of an expression is to compute a value, not to cause a side effect. The purpose of a statement is to cause a side effect. The call site of this thing would look an awful lot like an expression (though, admittedly, since the method is void-returning, the expression could only be used in a"statement expression" context.) It does not sit well with me to make the one and only sequence operator that is only useful for its side effects.
循环是更好的样式,因为它是为您想要做的事情而专门设计的工具。它与语言结合得更好。例如,可以从循环中断。工具了解循环,它们不了解ForEach。
这个循环对人类来说也更容易理解。ForEach非常罕见。
循环也更快,因为间接调用更少,委托分配更少,优化器可以在一个地方看到更多您正在做的事情。它还节省了ToList的调用。您也可以通过在IEnumerable上编写自定义扩展方法来保存该调用。
我认为这个循环在我能想到的所有情况下都是优越的。也许在某些情况下,ForEach方法的风格会更好,或者出于某种原因会更方便。
PLINQ也有一个ForAll,因为它可以并行化,所以出于效率的原因需要它。
- "更少的委托分配"该委托将被编译为一个方法,不是吗,这意味着它与使用普通方法调用的foreach没有什么不同。唯一的区别是.ToList(),正如您所说,它可以通过自定义扩展方法来解决…
- @lambda将编译为一个方法。然后,在构造传递给该方法的新分配委托时,将使用该方法。
- 我不太明白,因为他的例子也可以写成:.ForEach(WriteObject),它应该编译成我认为大致相同的IL代码。(如果我完成了我正在做的事情,出于好奇,我可能很快就会试试这个)
- @Phill,代码确实需要分配一个委托,你完全正确。这就是为什么它是foreach和foreach的区别,与lambda的使用无关。
- 投反对票,因为这主要是对个人偏好的一种意见回答。
- @达维达诺,我所说的一切都不是客观上有争议的。指出主观性的例子。
在大多数情况下,这是个人偏好的问题。谈论性能:
大多数时候,Linq会慢一点,因为它引入了开销。如果你很关心性能,就不要使用LINQ。使用LINQ是因为您需要更短、更易于阅读和维护的代码。
- foreach不是linq。
- 通过指定LINQ引入的开销以及在哪些情况下包含开销,可以改进这个答案。