使用foreach循环和LINQ的操作有什么区别?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (45)

我正在解决一个问题,我明白这些代码的工作方式不同,但我不明白为什么第二个代码不正确,有什么区别。

public Person GetOldestMember()
{
    Person oldestPerson = people.OrderByDescending(x => x.Age).FirstOrDefault();

    return oldestPerson;
}

.

public Person GetOldestMember()
{
    Person oldestPerson = new Person(-1); //this is a constructor with parameter age

    foreach (Person person in people)
    {
        if (person.Age > oldestPerson.Age)
        {
            oldestPerson = person;
        }
    }

    return oldestPerson;
}
提问于
用户回答回答于

关于LINQ查询的一个问题并不是很明显,它们往往会“快速失败”。也就是说,只要满足指定的条件,它们就会退出循环,而不是遍历整个序列。

例如,FirstOrDefault()如果序列中有任何项目,则从序列中获取第一个项目并立即退出。如果没有,则立即返回null。它不会迭代序列。

for但是,您的循环会迭代序列中的每个元素。如果序列非常大,则这可能是耗时的。此外,如果您的退出条件错误或完全丢失,您可能会返回错误的元素(尽管这也可能在LINQ表达式中发生)。

LINQ表达式非常高效,只检索尽可能快地完成请求所需的数据。你不太可能写一个更有效的for循环(虽然不是不可能)。

用户回答回答于
  • LINQ针对可读性进行了优化; 它易于编写,阅读和理解
  • 但它并不总是那么有效; 它不能利用自定义迭代器之类的东西,并且可能涉及更多对象
  • 简单的操作(OrderBy例如)可能非常昂贵
  • 但是......在大多数情况下,这无关紧要,可读性就是赢家
  • 但是......在某些情况下,这很重要 :)

如果我们假设这是内存中的数据(LINQ对象) -有点像IEnumerable<Person>List<Person>Person[],等:

请注意,排序是一项相对昂贵的操作,使用LINQ时通常也意味着创建数据副本(以便不更改源)。有一些外部扩展方法可以在LINQ概念中更有效地实现这一点,即

Person oldestPerson = people.MaxBy(x => x.Age);

同样,不是高效的循环,但效率比OrderByDescending+ FirstOrDefault...只是注意如何表现为空输入(它可能抛出而不是返回null)。

然而,正如Dzyann在评论中观察到的那样:people这里可能是一个IQueryable<Person>类似于DbSet<Person>EF或LINQ-to-SQL(等)的东西,在这种情况下,一切都在变化:现在我们讨论的是被推送到外部资源的查询,在这种情况下,OrderByDescending+ FirstOrDefault可以成为SQL,如:

SELECT TOP 1 *
FROM People
ORDER BY Age DESC

我们成了英雄。如果我们通过foreach一个IQueryable<Person>,我们会发出:

SELECT *
FROM People

当我们在本地迭代以查看哪个是最旧的时,然后通过网络获取所有内容

扫码关注云+社区

领取腾讯云代金券