如果数据源保持不变,则多次运行Enumerable

时间:2017-02-10 11:55:54

标签: c#

我了解IEnumerable可能会在多次运行时返回不同的结果。 但是,如果我们确定基础记录集之间永远不会发生变化并且循环序列根本不重要,那么这仍然是一个问题吗?

在任何地方致电ToList / ToArray而不考虑它只是一种“可能的”风险,真是太遗憾了。如果它永远不会发生,R#或VS可以简单地将其标记为错误。

这真的不例外吗? 我们不应该多次迭代IEnumerable吗?

这就是实际发生的事情。 在单线程环境中。

void Main()
{
    var result = GetFile(new [] {path1, path2})  // hardcoded path
}

IList<SomeFile> GetFiles(IEnumerable<string> filePaths)
{
    var paths = filePaths.ToArray();   // <-- why we have to do this ?

    foreach(var path In paths)
        // Throw exception if the path not exist.
    foreach (var path In paths)
        // Process and return a list of file
}

我理解它没有多大区别,因为集合太小但我们正处于开始实施需要处理大量静态数据的项目。如果适用于所有领域而不考虑是否有必要,这种做法可能是一个大问题。

2 个答案:

答案 0 :(得分:0)

在第二次迭代中获得不同结果的担忧远远超过了更为现实的性能问题。除非你的Requests实际上是内存中的集合,否则每次枚举时都有可能需要重现它。这可能非常昂贵:

  • 如果IEnumerable<T>来自另一个LINQ表达式,则需要花费CPU周期来重新计算同样的事情,
  • 如果IEnumerable<T>来自数据库,您最终可能会重新从服务器读取数据,
  • 如果IEnumerable<T>来自文件,您将重新阅读该文件。

以上都不会对正确性产生影响,但可能会大幅降低速度,尤其是对于大型数据集。由于内存目前相对便宜,垃圾收集系统非常可靠,暂时将集合保存在列表或数组中是避免问题的廉价方法。

答案 1 :(得分:0)

如果它是内存中的集合而不是抽象的可枚举对象 - 只需使用适当的接口(IReadOnlyCollection,IReadOnlyList等)而不是IEnumerable。如果你使用IEnumerable,你应该假设它可以是任何 IEnumerable实现。