C# 为什么可能会出现IEnumerable warning*的多次枚举而未显示

C# 为什么可能会出现IEnumerable warning*的多次枚举而未显示,c#,resharper,ienumerable,C#,Resharper,Ienumerable,我有点困惑,为什么Resharper、Studio或FX Cop不在下面的代码中警告我可能多次枚举IEnumerable: //warning here fine IEnumerable<IFileWrapper> filteredCollection = ctaWrappersContainer.FileContainer.Files.Where(x=>x.IsArchiveEntry); int y1 = filteredCollection.Count(); int y

我有点困惑,为什么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();
TL/DR:我同意@canton7,它会导致太多的误报。只是不要在属性中放置昂贵的枚举,这是一种糟糕的做法

长版本:

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

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

属性应该是轻量级的,不要把昂贵的计算放在那里
我想进一步指出,即使ReSharper可以警告您对属性进行昂贵的多重枚举,但属性返回昂贵的可枚举数据仍然是一种不好的做法。即使没有一个方法可以对这样的属性进行两次枚举,也可以有一个复杂的方法在一行中多次调用不同的枚举方法。在这种情况下,您的队友甚至不会考虑缓存对枚举结果的访问,因为属性是轻量级的,在几乎所有情况下缓存它们是没有意义的。

也许它不知道FileContainer.Files每次访问时都返回相同的IEnumerable。它有可能在其getter中创建一个新的IEnumerable。盲目添加此警告可能会产生大量误报。你能发布代码而不是图像吗?由于防火墙的限制,包括我在内的许多人都无法查看外部图像。@MatthewWatson-对不起,我没有意识到这一点!此外,谷歌对图像的搜索效果也不好。我们非常喜欢这里的代码和错误MSG作为文本。它不会警告您,原因与您调用Directory.EnumerateFiles两次时不会警告您相同,因为据它所知,这会给您两个单独的枚举数。因此,我同意/u/canton7的想法。
 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);
        }