C# 理解延迟执行性能

C# 理解延迟执行性能,c#,C#,假设我们有一份学生名单: var students = new List<Student>(//fill with 5000 students); 方法2: var youngestMaleStudent = students.Where(s => s.Gender == "male").OrderBy(s => s.Age).First(); Console.WriteLine(youngestMaleStudent.Name); var ma

假设我们有一份学生名单:

var students = new List<Student>(//fill with 5000 students);
方法2:

var youngestMaleStudent = students.Where(s => s.Gender == "male").OrderBy(s => s.Age).First();

Console.WriteLine(youngestMaleStudent.Name);
var maleStudents = students.Where(s => s.Gender == "male").ToList()

var youngestMaleStudent = maleStudents.OrderBy(s => s.Age).First();

Console.WriteLine(youngestMaleStudent.Name);
我认为方法1应该更有效,因为方法2创建了一个新的列表,并将所有内容都移动到其中,但据推测,这并不是一个大问题,因为复制内存相对较快?(尽管5000个物体可能开始减轻重量)

但我想,它们在性能方面是否有不同的运行方式?LINQ是如何处理方法1中的每个步骤的,它不需要将所有内容复制到某种形式的列表中,然后开始对数据进行排序吗?

在方法2中
.ToList()
iquirable
转换为
IEnumerable
,并在此基础上,从数据库获取所有数据,然后
学生。在哪里(s=>s.Gender==“male”)
在内存中对其应用条件

在方法1中,
youngestMaleStudent
iQuery
然后查询
students.Where(s=>s.Gender==“male”).OrderBy(s=>s.Age)。First();
在数据库端处理

结果是方法1的性能更好,特别是在数据量很大的情况下。

Linq允许对查询的不同部分进行排队或链接,如select、where和order,如SQL,在使用时执行,例如使用
foreach
ToList()

这是通过使用

因此方法1速度更快,因为在方法2中
ToList()
执行查询,然后
首先执行一个新查询。因此,在不考虑底层缓存和优化的情况下,最后一个查询最坏可能是2倍。因为它使用执行的查询(
ToList()
)对其执行orderby,这是第二次执行的查询(
First()

换句话说,在方法1中,查询仅由
First()
方法调用执行,之前的所有调用都会延迟,以准备此过程的最终查询,就像在字符串中添加参数一样(对于SQL,对于任何其他目标,情况大致相同)但是在方法2中,
ToList()
从一个消耗时间和内存的已执行查询创建一个
List
实例,然后调用
First()
对该列表执行另一个查询,再次消耗时间和内存

因此,重要的是检查每个Linq方法的文档是否延迟


Linq既可以是性能杀手,也可以是通心粉代码杀手,还可以是黑洞。

您尝试过吗?方法2需要至少再检查一次列表(与1相比),这是一种浪费处理时间的行为time@JohanDonne对潜在的为什么/如何比是/否
ToList()更感兴趣
会立即对从
.Where()
返回的
IEnumerable
进行完整的评估。如果不这样做,我希望生成的IL(以及因此产生的性能)是相同的。LINQ仍然需要在对雄性进行排序之前找到它们(或者按顺序进行排序,这意味着每次迭代都需要更多的计算)。那么它真的更快了吗?从来没有人提到过数据库,LINQ可以用来对付这个问题中的内存对象。除此之外,方法2在任何可能的情况下都不会表现得更好。我应该编辑我的答案。我想说方法1表现得更好。我现在编辑它。谢谢。方法1如何避免额外的工作ly?(注意这里没有db或SQL)。当它通过Where()运行时它可以找到所有的雄性,但一旦它完成了,它肯定需要去把它们全部排序。或者它在迭代过程中管理排序吗?@FBryant87我建议读一点源代码-注意,这不是小事code@FBryant87回答已更新。@Olivier谢谢,我知道电话被推迟了,但我还是不知道怎么会更快因此,在这个特定的场景中。在方法1中,LINQ仍然需要找到所有的雄性并对它们进行排序-那么在幕后,它是如何比方法2更快地实现这一点的呢?@FBryant87我写的是一般情况,尤其是对于数据库。但请记住,即使对于对象,.NET源代码也是优化的(可能是1个“循环”)对于方法1,而不是方法2的“循环”)。只有基准测试才能告诉您有关数据源和使用的数据量的真相。为避免不必要的Linq执行而进行的搜索应该是自动的,并且重构和保持代码干净。