我正在解决一个问题,并且我知道这些代码以不同的方式工作,但是我不明白为什么第二个代码不正确以及有什么区别。
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;
}
答案 0 :(得分:6)
OrderBy
)可能会非常昂贵 如果我们假设这是内存中数据(LINQ对象),则类似IEnumerable<Person>
,List<Person>
,Person[]
等
请注意,排序是一项相对昂贵的操作,使用LINQ时通常也意味着创建数据副本(以免更改源)。有 个外部扩展方法可以在LINQ概念中更有效地执行此操作,即
Person oldestPerson = people.MaxBy(x => x.Age);
再一次,而不是相当,其效率要比循环好,但吨的效率要比OrderByDescending
+ FirstOrDefault
...要注意对于空输入,它的行为是(可能会抛出而不是返回null
。)
但是,正如Dzyann在评论中观察到的那样:people
可能是IQueryable<Person>
-类似于EF或LINQ-to-SQL(等)中的DbSet<Person>
一切都会改变:现在,我们谈论的是将查询下推到外部资源的情况,在这种情况下,OrderByDescending
+ FirstOrDefault
可能会变成SQL,如:
SELECT TOP 1 *
FROM People
ORDER BY Age DESC
我们已经成为英雄。如果我们通过foreach
上的IQueryable<Person>
进行了此操作,我们将发出:
SELECT *
FROM People
然后在我们进行本地迭代以查看哪个最旧时通过网络获取了一切。
答案 1 :(得分:-2)
关于LINQ查询的一件事并不是立即显而易见的,它们往往会“快速失败”。也就是说,它们会在满足指定条件后立即退出循环,而不是遍历整个序列。
例如,FirstOrDefault()
从序列中获取第一个项目,如果序列中有任何项目,则立即退出。如果没有,则立即返回null。它不会遍历整个序列。
但是,您的for
循环遍历序列中的每个元素。如果序列非常大,则可能很耗时。此外,如果退出条件错误或完全丢失,则可能返回错误的元素(尽管在LINQ表达式中也可能发生)。
LINQ表达式非常高效,它仅以最快的速度检索满足请求所需的数据。您不太可能编写效率更高的for
循环(尽管并非不可能)。