【问题标题】:Resharper's 'Possible Multiple enumeration of IEnumerable warning' [duplicate]Resharper 的“IEnumerable 警告的可能多重枚举”[重复]
【发布时间】:2016-08-10 21:33:51
【问题描述】:

不重复:我不觉得这是重复的,因为在我的具体情况下,我觉得忽略警告实际上更好。

例如,

IEnumerable<Item> milionItems = GetAMillionItemsFromDatabase();

var item1 = millionItems.FirstOrDefault(x=> x.Condition == "Excellent");

var item2 = millionItems.FirstOrDefault(x=> x.Condition == "Good");

我在“millionItems”下收到警告消息,我知道这意味着什么,但我不确定是否总是值得 ToList'ing 只是为了摆脱它。

GetAMillionItemsFromDatabase().ToList();

这在性能方面似乎很糟糕,因为它会一次将一百万条记录带入内存。

但是,如果我不这样做并继续枚举 IEnumerable,即使它会访问数据库两次,它也不会将所有数据带入,因为它会找到第一个匹配项并返回。在这种情况下,在我看来,实际上忽略该消息会更好。

【问题讨论】:

  • 当然,忽略警告可以安全。这取决于枚举的内容。如果您尝试枚举它们两次,一些实现IEnumerable 的类将返回一个空集合。您需要确定最适合您的情况:将所有项目保存在一个列表中,进行多次可能昂贵的数据库调用,或者甚至可能放弃 LINQ 并编写一个循环,一次通过数据。 Enumerable.Aggregate 可能在这种情况下也有用。

标签: c# optimization resharper ienumerable


【解决方案1】:

在这种情况下,很有可能两次访问 DB 比通过在当前代码中执行的 IEnumerable 进行客户端搜索要好。

如果您无法将搜索推送到 DB(即通过保持 IQueryable&lt;Item&gt; 允许链接),您仍然可以通过检查每个项目的两个条件来稍微优化查找:

  foreach(var x in millionItems)
  {
     item1 = item1 == null && x=> x.Condition == "Excellent" ? x : item1;
     item2 = item2 == null && x=> x.Condition == "Good" ? x : item2;

     if (item1 != null && item2 != null)
     {
           break;
     }
  }

这很有可能会在客户端处理很多项目,但至少不会同时将它们保存在内存中。

如果这只是您需要构建的 2 个查询,则使用 ToList 转换为列表不太可能更好。

【讨论】:

    猜你喜欢
    • 2012-01-04
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多