Vb.net 如何判断何时枚举LINQ查询?

Vb.net 如何判断何时枚举LINQ查询?,vb.net,linq,Vb.net,Linq,一开始这似乎是个愚蠢的问题,但请继续读下去 我知道LINQ查询是延迟的,只有在枚举查询时才会执行,但我很难准确地确定何时会发生这种情况。当然,在For-Each循环中,查询将被枚举。经验法则是什么?如果是一个巨大的结果,我不想意外地枚举我的查询两次 例如,System.Linq.Enumerable.First是否对整个查询进行枚举?我询问性能原因。我想将LINQ结果集传递给ASP.NET MVC视图,还想分别传递第一个元素。将结果列举两次将是痛苦的 如果每次枚举LINQ查询时都启用某种标志来提

一开始这似乎是个愚蠢的问题,但请继续读下去

我知道LINQ查询是延迟的,只有在枚举查询时才会执行,但我很难准确地确定何时会发生这种情况。当然,在For-Each循环中,查询将被枚举。经验法则是什么?如果是一个巨大的结果,我不想意外地枚举我的查询两次

例如,System.Linq.Enumerable.First是否对整个查询进行枚举?我询问性能原因。我想将LINQ结果集传递给ASP.NET MVC视图,还想分别传递第一个元素。将结果列举两次将是痛苦的

如果每次枚举LINQ查询时都启用某种标志来提醒我,那就太好了。这样,当我意外地列举了两次时,我可以捕捉到场景。

您可以很容易地看到发生了什么。除此之外,懒惰/渴望的部分相当清楚。基本上,当返回类型为
IEnumerable
IORDerenumerable
时,它是懒惰的。这些人可能很懒惰,因为如果不调用
GetEnumerator()
,就无法获取任何数据。例如,将其与
First()
进行比较-它必须向您返回一个值。它不能拖延任何事情

一般来说,如果要确保查询不会被计算多次,请在查询上调用
ToList
ToArray
,然后多次使用该查询的结果。同样,这些方法必须立即返回列表或数组,这两种方法都不允许惰性填充。对查询进行了计算,但随后它实际上与生成的填充集合断开了连接-无论您对列表进行了多少检查,都不会再次执行查询


除了懒惰/急切的问题之外,还有流式/非流式:该方法是从源枚举中读取所有内容,还是在需要时对其进行“sip”读取。同样,一般来说,LINQ只会在必须的时候读取—所以当
Reverse
是非流式的(但仍然是惰性的),
Where
Select
是流式的。

对于何时枚举LINQ查询以及何时不枚举LINQ查询,没有硬性的规则。部分原因是某些方法将基于或不基于查询源的基础类型

这里是一个快速分解。这并不是一个完全的崩溃,主要是我能在5分钟内想出的

聚合函数 他们立即完整地列举了清单。它们通常由返回标量值的扩展方法发现。例如总和、最小值、最大值、计数、最后一次等

注意:Count和Last不一定枚举整个列表。如果基础类型可转换为
ICollection
,则它们将使用更有效的方法

列表选择器的前面 他们只看列表中的第一个元素,可能还有第二个。他们是第一,第一或默认,单身,单身或默认

上面提到的是不带谓词的版本。如果他们使用谓词,则最好将其归类为查询(见下文)

查询 它们只会枚举执行该操作所需的列表的最小数量。这可以是一个元素,也可以是整个列表

示例:任何,包含

创建一个新列表,不立即进行枚举。
这是LINQ中绝大多数的运营商。它们的成本是在新列表被枚举时产生的。示例:Select、Where、Group、Join、SkipWhile、Skip。

关于“列表选择器的前面”——当这些函数采用谓词时,它们可能会覆盖整个集合
First
将在第一个时停止(就像您的“查询”),但是
Single
也会检查它是否是唯一的一个。我相信你知道,但我想应该注意一下。@Kobi,实际上我忘了有一个重载包含谓词。我会为你的帖子更新。我希望我也能将此作为一个答案,但我真的从Jon Skeet关于日志记录的博客文章中得到了很多。