【问题标题】:C# Why is possible multiple enumerations bad? [duplicate]C# 为什么可能的多个枚举不好? [复制]
【发布时间】:2021-10-19 17:40:09
【问题描述】:

Visual Studio 在IEnumerable 上向我发出警告“警告:可能存在多个枚举”。然后我添加ToList() 到它。但我开始怀疑为什么这是一种不好的做法。

那么为什么多次列举不好呢?

【问题讨论】:

  • 有些序列不能被枚举多次,或者在多次枚举时会给你不同的结果。
  • 只是为了添加到@MatthewWatson,您可能从数据库或网络服务或其他一些相对“慢”的共享资源中提取了一个序列。多次枚举意味着多次访问资源,这将减慢您的程序,或减慢共享资源,或两者兼而有之。
  • @cly 可忽略
  • @ErmiyaEskandary 对 10m 项的快速经验测试表明您是正确的,尽管 ToList 的时间值几乎是 ToArray 的两倍,但结果仍然在 10 毫秒的范围内,因此可以忽略不计。这里有关于这个主题的主题,比如这个旧主题:stackoverflow.com/questions/454916/… 有人感兴趣。

标签: c# enumeration


【解决方案1】:

“IEnumerable 的可能多重枚举”是一个更清晰的警告。如果您多次枚举一个可枚举项,ReSharper 将检测到这一点并警告您。虽然这个警告一开始可能看起来毫无意义,但有两个很好的理由来关注它:

  1. 枚举一个可枚举对象可能非常昂贵。例如,可枚举可能由数据库支持。重新枚举可能会迫使您等待另一个网络往返。您不想支付两次费用。

  2. 多个枚举自身复合导致的性能问题。

请查看这篇文章以获取有关此警告的更多信息:http://twistedoakstudios.com/blog/Post7694_achieving-exponential-slowdown-by-enumerating-twice

【讨论】:

  • 还有第三个更重要的原因;枚举不保证可重复 - 它可能返回完全不同的数据,或者根本无法重复;例如,考虑一个可枚举,它通过打开的Socket(它不控制另一端)从外部数据中提取,或者数据来自某种 RNG(特别是 CRNG 或 PRNG其中种子不是枚举器源的一部分)
【解决方案2】:

在 IEnumerable 中枚举项目的成本可能很高,具体取决于实现类型。在内存中对 List 进行多次枚举并没有太大区别。如果 IEnumerable 是数据库选择器,则使用 toList() 对其进行迭代可能会更快,然后对列表进行迭代

【讨论】:

    【解决方案3】:

    您实际上是在代码中循环两次集合,这就是您收到 ReSharper 警告的原因。

    例如,当使用由数据库调用返回的IEnumerable 时,这意味着获取数据两次,从而减慢您的应用程序并导致不必要的数据库负载。为什么要获取两次数据?

    如果在内存中使用可枚举,根据集合的大小对集合进行多次枚举也可能非常昂贵。

    使用.ToList() 可以解决错误,因为它通过将IEnumerable 转换为列表来强制在变量初始化点进行枚举(您也可以通过使用ToArrayIEnumerable 强制转换为数组) .

    IEnumerable 集合中的数据也可能在枚举之间发生变化,因此最好在需要数据保留的位置强制枚举(每次循环遍历它们时,可枚举中的项目可能不同)。

    JetBrains 本人:Code Inspection: Possible multiple enumeration of IEnumerable

    【讨论】:

      猜你喜欢
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      相关资源
      最近更新 更多