是否“foreach"导致重复的 Linq 执行? [英] Does "foreach" cause repeated Linq execution?

查看:22
本文介绍了是否“foreach"导致重复的 Linq 执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次使用 .NET 中的实体框架,并且一直在编写 LINQ 查询以从我的模型中获取信息.我想从一开始就养成良好的编程习惯,所以我一直在研究编写这些查询的最佳方式,并得到他们的结果.不幸的是,在浏览 Stack Exchange 时,我似乎遇到了关于延迟/立即执行如何与 LINQ 一起工作的两个相互矛盾的解释:

I've been working for the first time with the Entity Framework in .NET, and have been writing LINQ queries in order to get information from my model. I would like to program in good habits from the beginning, so I've been doing research on the best way to write these queries, and get their results. Unfortunately, in browsing Stack Exchange, I've seem to have come across two conflicting explanations in how deferred/immediate execution works with LINQ:

  • foreach 导致查询在循环的每次迭代中执行:

证明有问题 慢 foreach() 在 LINQ 查询上 - ToList() 极大地提高了性能 - 为什么会这样? ,这意味着需要调用ToList()"才能立即评估查询,因为 foreach 正在评估重复查询数据源,大大减慢操作速度.

Demonstrated in question Slow foreach() on a LINQ query - ToList() boosts performance immensely - why is this? , the implication is that "ToList()" needs to be called in order to evaluate the query immediately, as the foreach is evaluating the query on the data source repeatedly, slowing down the operation considerably.

另一个例子是Foreaching through grouped linq结果非常慢,有什么提示吗?,其中接受的答案还暗示在查询上调用ToList()"会提高性能.

Another example is the question Foreaching through grouped linq results is incredibly slow, any tips? , where the accepted answer also implies that calling "ToList()" on the query will improve performance.

  • foreach 使查询执行一次,并且可以安全地与 LINQ 一起使用

证明有问题 foreach 是否只执行一次查询?,言下之意是foreach导致建立一个枚举,不会每次都查询数据源.

Demonstrated in question Does foreach execute the query only once? , the implication is that the foreach causes one enumeration to be established, and will not query the datasource each time.

继续浏览该站点会发现许多问题,其中在 foreach 循环期间重复执行"是性能问题的罪魁祸首,还有很多其他答案表明 foreach 将适当地从数据源中获取单个查询,这意味着这两种解释似乎都有效.如果ToList()"假设不正确(截至 2013-06-05 1:51 PM EST 的大多数当前答案似乎暗示),那么这种误解来自哪里?这些解释中是否有一种是准确的,另一种是不准确的,或者是否存在可能导致 LINQ 查询以不同方式评估的不同情况?

Continued browsing of the site has turned up many questions where "repeated execution during a foreach loop" is the culprit of the performance concern, and plenty of other answers stating that a foreach will appropriately grab a single query from a datasource, which means that both explanations seem to have validity. If the "ToList()" hypothesis is incorrect (as most of the current answers as of 2013-06-05 1:51 PM EST seem to imply), where does this misconception come from? Is there one of these explanations that is accurate and one that isn't, or are there different circumstances that could cause a LINQ query to evaluate differently?

除了下面接受的答案之外,我在程序员上提出了以下问题,这非常有助于我理解查询执行,特别是可能导致多个数据源命中的陷阱循环,我认为这对其他对此问题感兴趣的人会有所帮助:https://softwareengineering.stackexchange.com/questions/178218/for-vs-foreach-vs-linq

推荐答案

通常 LINQ 使用延迟执行.如果您使用像 First()FirstOrDefault() 这样的方法,查询会立即执行.当你做类似的事情时;

In general LINQ uses deferred execution. If you use methods like First() and FirstOrDefault() the query is executed immediately. When you do something like;

foreach(string s in MyObjects.Select(x => x.AStringProp))

以流式方式检索结果,意思是一个一个.每次迭代器调用 MoveNext 时,投影都会应用到下一个对象.如果您有一个 Where,它将首先应用过滤器,然后应用投影.

The results are retrieved in a streaming manner, meaning one by one. Each time the iterator calls MoveNext the projection is applied to the next object. If you were to have a Where it would first apply the filter, then the projection.

如果你做类似的事情;

List<string> names = People.Select(x => x.Name).ToList();
foreach (string name in names)

那么我认为这是一个浪费的操作.ToList() 将强制执行查询,枚举 People 列表并应用 x =>x.Name 投影.之后,您将再次枚举该列表.因此,除非您有充分的理由将数据放在列表中(而不是 IEnumerale),否则您只是在浪费 CPU 周期.

Then I believe this is a wasteful operation. ToList() will force the query to be executed, enumerating the People list and applying the x => x.Name projection. Afterwards you will enumerate the list again. So unless you have a good reason to have the data in a list (rather than IEnumerale) you're just wasting CPU cycles.

一般来说,对使用 foreach 枚举的集合使用 LINQ 查询的性能不会比任何其他类似且实用的选项差.

Generally speaking using a LINQ query on the collection you're enumerating with a foreach will not have worse performance than any other similar and practical options.

另外值得注意的是,我们鼓励实现 LINQ 提供程序的人使常用方法像在 Microsoft 提供的提供程序中那样工作,但他们不是必需的.如果我要编写 LINQ to HTML 或 LINQ to My Proprietary Data Format provider,则无法保证它会以这种方式运行.也许数据的性质会使立即执行成为唯一可行的选择.

Also it's worth noting that people implementing LINQ providers are encouraged to make the common methods work as they do in the Microsoft provided providers but they're not required to. If I were to go write a LINQ to HTML or LINQ to My Proprietary Data Format provider there would be no guarantee that it behaves in this manner. Perhaps the nature of the data would make immediate execution the only practical option.

另外,最终编辑;如果您对此感兴趣,Jon Skeet 的 C# In Depth 内容丰富,值得一读.我的回答总结了本书的几页内容(希望具有合理的准确性),但如果您想了解更多有关 LINQ 如何在幕后工作的详细信息,这是一个不错的地方.

Also, final edit; if you're interested in this Jon Skeet's C# In Depth is very informative and a great read. My answer summarizes a few pages of the book (hopefully with reasonable accuracy) but if you want more details on how LINQ works under the covers, it's a good place to look.

这篇关于是否“foreach"导致重复的 Linq 执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆