ReSharper的“可能枚举IEnumerable警告”

3

非重复:我认为这不是一个重复的问题,因为在我的情况下,忽略警告实际上更好。

例如,

IEnumerable<Item> milionItems = GetAMillionItemsFromDatabase();

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

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

我在'millionItems'下面收到了警告消息,我知道这是什么意思,但我不确定是否总是值得进行ToList操作来消除它。

GetAMillionItemsFromDatabase().ToList();

这样做在性能方面看起来很糟糕,因为它会一次性将一百万条记录导入内存。

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


当然,忽略警告可能是安全的。这取决于正在枚举的内容。一些实现IEnumerable接口的类在尝试两次枚举时将返回一个空集合。您需要确定在您的情况下什么最好:将所有项目保存在列表中,进行多个潜在昂贵的数据库调用,甚至放弃LINQ并编写循环以在数据上进行单次获取item1item2。在这种情况下,Enumerable.Aggregate可能也会有用。 - Jim Mischel
1个回答

5

在这种情况下,去数据库两次的机会非常好,比起当前代码执行的基于IEnumerable的客户端搜索来说,效果更佳。

如果你无法将搜索推送到数据库(例如保持IQueryable<Item>以允许链接),你仍然可以通过在每个项上检查两个条件来优化查找:

  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;
     }
  }

这段代码有很大的机会在客户端处理大量数据,但至少不会同时占用内存。

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


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