【问题标题】:Why is Possible Multiple Enumeration of IEnumerable warning *not* shown为什么可能多次枚举 IEnumerable 警告 *未显示 *
【发布时间】:2019-12-02 11:20:21
【问题描述】:

我有点困惑,为什么 Resharper(也不是 Studio 或 FX Cop:))在下面的代码中再次警告我可能对 IEnumerable 进行多次枚举:

//warning here fine
 IEnumerable<IFileWrapper> filteredCollection = ctaWrappersContainer.FileContainer.Files.Where(x=>x.IsArchiveEntry);
int y1 = filteredCollection.Count();
int y2 = filteredCollection.Count();

//why no warning here?
int countOfIenumerable = ctaWrappersContainer.FileContainer.Files.Count();
int countOfIenumerableAgain = ctaWrappersContainer.FileContainer.Files.Count();

Files 集合是一个真正的 IEnumerable,每次调用都会重新计算。 以下是在代码中某处分配 Files 属性的方式:

container.Files = this.GetFilesFromArchive(container, zipFile.FullName, searchPattern);

GetFilesFromArchive() 正在枚举条目并一一返回(基于某些过滤器)。 因此,每次我调用计数时,它都会再次执行此操作(如预期的那样)

 protected override IEnumerable<IFileWrapper> GetFilesFromArchive(FileContainer fileContainer, string zipFilePath, string searchPattern)
        {
           //do some filtering magic on a collection of entries in a zip
          yield return new ZipEntryWrapper(fileContainer, zipEntry, zipFile);
        }

【问题讨论】:

  • 也许它不知道FileContainer.Files 每次访问时都返回相同的IEnumerable&lt;T&gt;。它有可能在其吸气剂中创建一个新的IEnumerable&lt;T&gt;。盲目添加此警告可能会产生大量误报。
  • 你能发布代码而不是图像吗?由于防火墙限制,许多人(包括我自己)无法查看外部图像。
  • @MatthewWatson - 抱歉,没有意识到这一点!
  • 另外,图片不能很好地用谷歌搜索。我们非常喜欢这里的代码和错误消息作为文本。
  • 它不会警告您,原因与您拨打Directory.EnumerateFiles() 两次时它不会警告您的原因相同——因为据它所知,这会给您两个单独的可枚举项。所以我同意 /u/canton7 的想法。

标签: c# resharper ienumerable


【解决方案1】:

TL/DR:我同意@canton7,这会导致太多误报。只是不要在属性中放置昂贵的枚举,这是一种不好的做法。

长版:

无法判断枚举是否昂贵
基本上,对可能的多重枚举的检查试图警告您潜在的性能问题,因为IEnumerable 通常来自数据库查询等昂贵的计算。但是 ReSharper 无法确定枚举是否真的很昂贵,因为跟踪所有可枚举的来源将非常复杂且非常缓慢,并且在某些情况下是不可能的(可枚举来自类库中的接口或虚拟方法,并且覆盖可能是在外部代码中)。

可枚举属性通常用于封装简单的集合
这也适用于可枚举属性:ReSharper 无法确定该可枚举是否具有昂贵的枚举。如果它仍然继续并警告同一可枚举属性的多个枚举,则会导致太多误报,因为许多程序员不会将昂贵的枚举放入属性中。大多数情况下,可枚举属性在后台返回基本集合,如 List 或 HashSet,并选择返回类型 IEnumerable 来封装实现细节并允许开发人员稍后将实现集合更改为其他内容。虽然现在我们有IReadOnlyCollection,它更适合这种封装,但我们仍然有大量带有IEnumerable 的旧代码。

属性是轻量级的,不要在那里进行昂贵的计算
我会进一步争辩说,即使 ReSharper 可以警告您对属性进行昂贵的多重枚举,但属性返回昂贵的可枚举仍然是一种不好的做法。即使您没有对此类属性进行两次枚举的单一方法,您仍然可以拥有一个复杂的方法,该方法会连续多次调用不同的枚举方法。在这种情况下,您的队友甚至不会考虑缓存对枚举结果的访问,因为属性是轻量级的,几乎在所有情况下都没有缓存它们的意义。

【讨论】:

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