[英]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.