[英]Is it more efficient to perform a LINQ in a foreach statement?
这些陈述做同样的事情吗?
var listA = someList.TakeWhile(predicate);
foreach(var item in listA)
{
/// perform code here
}
相对...
foreach(var item in someList.TakeWhile(predicate))
{
/// perform some code here
}
是先创建集合,然后迭代 O(N^2) 吗? 还是集合在创建 O(N) 时迭代?
@Jeremy Lakeman 在评论中提供了正确答案。
变量listA
的类型在:
var listA = someList.TakeWhile(predicate);
是IEnumerable<T>
, T 是集合someList
的单个元素的类型。 TakeWhile
方法的签名清楚地表明了这一点:
public static System.Collections.Generic.IEnumerable<TSource> TakeWhile<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,int,bool> predicate);
可以在TakeWhile
文档页面中看到。
声明IEnumerable<T>
类型的变量不会枚举它。 要枚举IEnumerable
,您必须明确地进行操作,例如在foreach
循环中枚举它,或者使用它来生成新的物化集合,例如List
、 Dictionary
等……通过调用.ToList()
等方法.ToList()
或ToDictionary()
等...
这在(例如) ToList
文档中明确说明:
ToList<TSource>(IEnumerable<TSource>)
方法强制立即进行查询评估并返回包含查询结果的List<T>
。 您可以将此方法附加到查询中,以获取查询结果的缓存副本。ToArray
具有类似的行为,但返回一个数组而不是List<T>
。
因此,在您的两个代码示例中,您构造的IEnumerable
将在foreach
循环中仅枚举一次。
另外:即使您在枚举之前已经实现了您的集合:
var listA = someList
.TakeWhile(predicate)
.ToList(); // Notice the .ToList() call that forces the enumeration.
foreach(var item in listA)
{
/// perform code here
}
它仍然是 O(n) 操作,而不是 O(n^2)。 如果您从someList
集合中获取 N 个元素,您将使用.ToList()
调用枚举它们一次,并在foreach
循环中枚举它们一次,总共 2 x N,而不是 N^2。
两种形式都是一样的。 根据 Microsoft 文档,在直接或通过 foreach 调用其GetEnumerator
方法之前,查询 ( TakeWhile
) 不会执行。
在通过直接调用其
GetEnumerator
方法或使用 Visual C# 中的foreach
或 Visual Basic 中的For Each
枚举对象之前,不会执行此方法表示的查询。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.