簡體   English   中英

在 foreach 語句中執行 LINQ 是否更有效?

[英]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循環中枚舉它,或者使用它來生成新的物化集合,例如ListDictionary等……通過調用.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM