c# - Select 后跟 Where 会导致对 IEnumerable 进行两次迭代吗?

标签 c# performance linq linq-to-objects

假设我有

IEnumerable<int> list = new int[] { 1, 2, 3 };
List<int> filtered = list.Select(item => item * 10).Where(item => item < 20).ToList();

问题是有两次迭代还是只有一次。

换句话说,性能是否等同于:

IEnumerable<int> list = new int[] { 1, 2, 3 };
List<int> filtered = new List<int>();
foreach(int item in list) {
    int newItem = item * 10;
    if(newItem < 20)
        filtered.Add(newItem);
}

最佳答案

当您调用 .ToArray 方法时,会对集合执行一次迭代,因此两者应该是等效的。 .Select 是一个投影,.Where 是一个过滤器,都表示为原始数据集上的表达式树。

可以很容易地证明:

public class Foo: IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        yield return 1;
        Console.WriteLine("we are at element 1");
        yield return 2;
        Console.WriteLine("we are at element 2");
        yield return 3;
        Console.WriteLine("we are at element 3");
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

class Program
{
    static void Main()
    {
        var filtered = new Foo()
            .Select(item => item * 10)
            .Where(item => item < 20)
            .ToList();
    }
}

运行时打印如下:

we are at element 1
we are at element 2
we are at element 3

关于c# - Select 后跟 Where 会导致对 IEnumerable 进行两次迭代吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7988146/

相关文章:

c# - Builder 与 Facade 设计模式

performance - 何时在我的tal :condition?上使用nocall

python - 2向量矩阵点积的性能

c# - 这个带有 "arrow"的 C# 代码是什么意思,它是如何调用的?

c# - 在方法范围之外定义 "var"类型

c# - 将项目添加到 Listview 控件

c# - 如何在运行时延迟绑定(bind) 32 位/64 位库

C# JSON反序列化: can I intercept the deserialization and optionally change the result?

performance - 加载模块时的 Node js 性能

c# - 有没有一种简单的方法可以在 LINQ to Entities 中编写自定义函数?