LINQ扩展如何链式调用其他扩展方法?

3

我在2006年学习了C#,最近又想重新学习它。我发现他们在C#3.0中添加了一些东西,叫做LINQ扩展。现在我熟悉扩展方法,并且只是在思考与IEnumerables相关的具体细节。

今天早些时候,我和我的一个同事在争论以下代码块是否等价:

List<int> integers;
IEnumerable<int> subResult = items.Where(i => IsPrime(i));
IEnumerable<int> orderedResult = subResult.OrderBy(i => i);

对比

List<int> integers;
IEnumerable<int> result = items.Where(i => IsPrime(i)).OrderBy(i => i);

他告诉我最新的版本更高效,因为该扩展使用了延迟查询其来源的方法。我不太确定我理解他的意思,想知道他是否正确。

4个回答

5
它们是等价的。它们都使用惰性求值/延迟查询。
这意味着当调用.Where方法时,它不执行任何实际的列表枚举,只保留对其输入和要检查的条件的引用并存储这些引用。当稍后在.Where的结果上调用GetEnumerator方法时,.Where开始工作。
与.OrderBy相同。直到调用.GetEnumerator才会真正枚举列表。
这些东西可能很难理解,但有几种非常好的学习方法。首先编写一个简单的示例,像您一样,最好分成多行,使用简单的for-each循环来迭代所有项目。调试代码并逐行跟踪。看看调试器如何跳转。起初非常令人困惑,但运行几次,您就会了解惰性求值的工作原理。
Jon Skeet还有一个精彩的演示来可视化LINQ。

https://msmvps.com/blogs/jon_skeet/archive/2008/02/20/visual-linq-watch-query-expressions-as-they-happen.aspx


3

他错了。

这两个代码块是相同的。
事实上,如果你没有在其他地方使用subResult,它们应该在发布模式下编译成完全相同的IL。


1

LINQ是在IEnumerable上实现的扩展方法。您可以将使用LINQ查询视为两个步骤的过程。首先,您定义查询,然后迭代查询。直到第二步,您实际上正在迭代查询之前,它还没有执行。

这两个示例在功能上是等效的,它们都不会在您迭代结果之前实际执行查询,此时两个LINQ查询运算符(Where和OrderBy)将执行并返回其适当的可枚举结果给其他代码执行迭代。


0

延迟执行和扩展方法是完全不同的概念。

没有扩展方法语法:

var result = System.Linq.Enumerable.Where(
   myList, a => a.CustomerName == "Bob");

通过扩展方法,myList 看起来有 Where 方法(但实际上没有)。
var result = myList.Where(a => a.CustomerName == "Bob");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接