Select 后跟Where 是否会导致对IEnumerable 进行两次迭代?

发布于 2024-12-13 12:19:19 字数 481 浏览 0 评论 0原文

假设我有

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);
}

Let say I have

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

The question is are there two iterations or just one.

In other words, is that equivalent in performance to:

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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

樱花落人离去 2024-12-20 12:19:19

当您调用 .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

There is a single iteration over the collection performed when you call the .ToArray method so both should be equivalent. .Select is a projection and .Where is a filter, both expressed as expression trees on the original dataset.

Could be easily proven:

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();
    }
}

when run prints the following:

we are at element 1
we are at element 2
we are at element 3
格子衫的從容 2024-12-20 12:19:19

在 Linq to Objects 中,WHERE 和 SELECT 不会迭代可枚举值。当调用代码对查询或 ToList 或 ToArray() 等执行 foreach 时,调用代码会枚举它

。在 Linq to SQL 中,没有任何迭代。当您执行 ToList 或 ToArray() 时,查询由数据库执行。根据查询的类型,数据库可以查找索引或进行表扫描。

In Linq to Objects WHERE and SELECT do not iterate over the enumerable. The calling code enumerates it when it does a foreach on the query or ToList or ToArray(), etc.

In Linq to SQL there is no iteration what so ever. When you do ToList or ToArray() the query is executed by database. Depending on the type of query db could look up indexes or do a table scan.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文