LINQ实现 - 一个循环还是多个?

时间:2011-01-26 14:30:23

标签: c# linq

说我有collection.Select(..).Where(...).Sum(...)

之类的东西

LINQ引擎会对集合执行1个或多个循环吗?

3 个答案:

答案 0 :(得分:8)

Sum会消耗过滤器Where的输出,这会消耗投影Select的输出,这将消耗collectionSum会将过滤后的序列移动一次,这会使投影走一次,这将导致collection一次。因此,集合将重复一次。

这是一个可爱的实验,你可以做到这一点:

class Sequence : IEnumerable<int> {
    public IEnumerator<int> GetEnumerator() {
        for (int i = 0; i < 17; i++) {
            Console.WriteLine(i);
            yield return i;
        }
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }
}

然后:

Sequence sequence = new Sequence();
int sum = sequence.Select(x => 2 * x).Where(x => x % 4 == 0).Sum();
Console.WriteLine("Sum is {0}", sum);

输出将是:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Sum is 144

显示sequence只迭代一次。

答案 1 :(得分:4)

这是一个类比(由于Jon Skeet),可以让你感受到这里发生的事情。

假设你有一个名为Collection的人有一副扑克牌。

“收集”旁边是“X X不是面卡”。

除了“Where”是“选择将卡值转换为整数”

“选择”旁边是“总和”。

你戳总和。 Sum进入循环。

总和选择。选择进入循环。

选择没有任何东西给Sum,所以选择戳到哪里。哪里进入循环。

pokes收集。收藏之手黑桃之王。

在哪里把它扔在地板上并再次捅收集。收藏之手那里的钻石女王,哪里扔在地板上。再次戳戳集合,这次集合手中的三心之心。

手中的三颗心选择。选择提取数字3并将其交给Sum。 Sum将其添加到零,然后返回到循环的顶部,并再次选择Select。

选择恢复循环,戳到哪里。在恢复循环的地方,反复戳戳Collection,直到Collection给出Where接受的地方。

所以它就是这样,将收集牌交给Where,在哪里扔掉它们或将它们传递给Select,并选择将数字输入Sum,这样可以保持一个总计。

当Collection最终说“没有”到Where,Where说“不再”选择时,Select会说“不再”为Sum,而Sum则返回给你的总和。

答案 2 :(得分:2)

这三个命令将有一个循环。

如果您想了解更多信息,我推荐Jon Skeet's blog,其中描述了LINQ to Objects的重新实现。