2013-08-23 34 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)