2013-08-23 60 views
2

鏈接LINQ語句是否會導致多次迭代?鏈接LINQ語句是否會導致多次迭代?

例如,假設我想用一個where子句來篩選數據,然後對比賽做一個總和:

int total = data.Where(item => item.Alpha == 1 && item.Beta == 2) 
    .Sum(item => item.Qty); 

這是否導致了數據的單一互爲作用,使得它會相當於這個?

int total = 0; 
foreach (var item in data) 
    if (item.Alpha == 1 && item.Beta == 2) 
     total += 1; 

或者,它遍歷data一次,where結果第二次做的總和?

回答

4

LINQ中的語句是流式傳輸的,因此Where實際上並不運行,直到Sum枚舉其值。這意味着從data項目將有效地一次枚舉。

基本上,Where方法創建一個新的IEnumerable<T>,但實際上並沒有通過data列舉。 SumIEnumerable<T>Where之間執行foreach,而該順序又通過Where順序一次抽取項目。

+0

我明白,這是推遲到評估,但它迭代兩次?一次爲了哪裏,一次是爲了總和? – Matt

+0

@Matt它不會「迭代」,直到達到「Sum」。我試圖編輯更清晰。 –

+0

太棒了!除了做一個.ToList()或.ToArray(),是否有任何LINQ查詢會導致多個枚舉? – Matt

3

是的,該LINQ查詢將只會導致源集合上的一次迭代。

它是如何工作的? Sum請求當時有一個元素,Where也是(源集合)。所以,當Sum需要下一個元素,它調用MoveNextEnumerator<T>Where拍攝,這是如下實現的:

foreach(var item in source) 
    if(predicate(item)) 
     yield return item; 

要了解越多,你應該閱讀有關迭代器:Iterators (C# and Visual Basic)