找出哪些.net框架linq方法(例如.IEnumerable linq方法)使用延迟执行而不是使用延迟执行实现的最快方法是什么。
编码多次,我想知道这个是否会以正确的方式执行。找出答案的唯一方法是访问MSDN文档以确保。会不会有更快捷的方式,任何目录,网络上的任何列表,任何备忘单,你可以分享的任何其他技巧?如果是,请这样做。这将有助于许多linq新手(像我一样)减少错误。唯一的另一个选择是检查文档,直到一个人使用它们足够记住(这对我来说很难,我往往不记得某些地方记录的“任何东西”,可以查找:D)。
答案 0 :(得分:35)
通常返回序列的方法使用延迟执行:
IEnumerable<X> ---> Select ---> IEnumerable<Y>
和返回单个对象的方法不会:
IEnumerable<X> ---> First ---> Y
因此,Where
,Select
,Take
,Skip
,GroupBy
和OrderBy
等方法会使用延迟执行,因为它们可以First
,Single
,ToList
和ToArray
等方法不会,因为它们不能。
还有两种类型的延迟执行。例如,Select
方法只会在要求生成项目时获得一个项目,而OrderBy
方法在被要求返回第一个项目时必须使用整个源项目。因此,如果您在OrderBy
之后链接Select
,则执行将推迟到您获得第一个项目,但OrderBy
将询问Select
所有项目
答案 1 :(得分:8)
我使用的指南:
始终假设任何返回IEnumerable<T>
或IQueryable<T>
的API都可以并且可能会使用延迟执行。如果您正在使用这样的API,并且需要多次迭代结果(例如,获取Count),那么在执行此操作之前转换为集合(通常通过调用.ToList()扩展方法。
如果您正在公开枚举,请始终将其公开为集合(ICollection<T>
或IList<T>
),如果这是您的客户通常会使用的。例如,数据访问层通常会返回域对象的集合。如果延迟执行是您正在公开的API的合理选项,则仅公开IEnumerable<T>
。
答案 2 :(得分:5)
实际上,还有更多;此外,您需要考虑缓冲与非缓冲。 OrderBy可以延迟,但迭代时 必须使用整个流。
通常,返回IEnumerable 的LINQ中的任何内容都会延迟 - 而Min等(返回值)不会延迟。缓冲(vs not)通常可以被推理,但坦率地说反射器是一种非常快速的方法来确定。但请注意,这通常是一个实现细节。
答案 3 :(得分:2)
对于实际的“延迟执行”,您需要适用于IQueryable的方法。基于IQueryable工作的方法链,用于构建表示查询的表达式树。只有当你调用一个接受IQueryable并产生具体或IEnumerable结果的方法(ToList()和类似的,AsEnumerable()等)时,Linq提供者才会评估它(Linq2Objects内置于Framework中,Linq2SQL和现在MSEF;其他ORM和持久层框架也提供Linq提供者)并返回实际结果。可以使用AsQueryable()扩展方法将框架中的任何IEnumerable类强制转换为IQueryable,并且将转换表达式树的Linq提供程序(如ORM)将提供AsQueryable()作为linq查询的跳转点。他们的数据。
即使针对IEnumerable,一些Linq方法也是“懒惰的”。因为IEnumerable的优点在于您不必了解所有内容,只有当前元素以及是否有另一个,作用于IEnumerable的Linq方法通常返回一个迭代器类,每当从源中吐出一个对象时后来在链中的方法要求一个。任何不需要了解整个集合的操作都可以进行延迟评估(选择和哪里有两个大的;还有其他的)。确实需要了解整个集合(通过OrderBy进行排序,使用GroupBy进行分类以及像Min和Max这样的聚合)将会将其整个源可以插入到List或Array中并对其进行处理,从而强制通过所有更高节点评估所有元素。一般来说,如果你能帮助它们,你希望这些在方法链中来得晚。
答案 4 :(得分:2)
以下是您可以了解是否推迟查询的多种方式的摘要:
如果您使用查询表达式语法而不是查询方法语法,则将其推迟。
如果您使用的是查询方法语法,则可能会根据其返回的内容来推迟它。
将鼠标悬停在关键字var
上(如果这就是您用来存储查询的变量的类型)。如果显示IEnumerable<T>
,则将其推迟。
尝试使用foreach遍历查询。如果您收到一条错误消息,说它由于不支持GetEnumerator()
而不能遍历变量,那么您就知道查询不会被推迟。
来源:Essential Linq
答案 5 :(得分:1)
如果使用.AsQueryable()将集合强制转换为IQueryable,则LINQ调用将使用延迟执行。