Visual Studio代码分析规则 - "不公开通用列表"

Fra*_*aga 10 c# linq extension-methods code-analysis fxcop

不要公开通用列表

如果我的所有方法都需要公开一个集合,那么我需要使用Linq扩展.ToList(),几乎我需要在所有代码中使用列表或用户集合.

如果是这种情况,.ToList()忽略规则吧?或者是否有一种技术,如复制列表,以修复违规并仍然返回列表?

Jar*_*Par 8

我禁用了该规则,因为我觉得它不是有效的规则.如果要返回包含O(1)计数且不是对内部字段的直接引用的集合,List<T>则是最佳选择.

我不太了解你的情况,但听起来你有一个方法可以通过某些内部数据返回LINQ查询.如果是这种情况,则使用.ToList()数据是合适的,因为您可能不希望将来修改内部字段以影响方法的返回值.在这种情况下,没有理由不将其暴露为List<T>.

  • 如果你想返回一个列表,`IList <T>`最好是返回类型.我通常仍然使用`IEnumerable <T>`作为返回类型(即使我调用`.ToList()`或`.ToArray()`),因为这为实现方法提供了更大的灵活性.当底层对象是`IList <T>`时,大多数LINQ函数足够智能以优化访问.特别是,`.Count()`和`.ElementAt()`都是O(1)操作,因此返回`IEnumerable <T>`不会对性能造成重大影响. (5认同)
  • 无论如何,他们更像是"指导方针". (4认同)
  • @ R. Bemrose,我相信,如果你返回一个`List <T>`,你就会暴露一个实现细节.如果您的函数稍后使用某些不同的数据结构,则更改返回类型将是一个重大更改,因此您最终可能会创建一个副本或包装器以维护公共接口.你必须决定你希望在公共合同中保证多少信息,越少越好. (2认同)

Nic*_*era 8

这个规则确实很吵,但List<T>在库代码中有一些非常有效的理由可以避免.这一切都取决于具体情况.在禁用规则或抑制给定事件之前,需要考虑以下几点:

  • List<T>输入参数通常是一个糟糕的选择,因为它会强制调用者不必要地复制数据.我已经看到很多代码声明参数List<T>T[]什么时候IEnumerable<T>就足够了.

  • List<T>也可能是物业的不良选择.考虑以下备选方案:

    public class Course {
        public List<Course> Prerequisites { get; }
    }
    public class Course {
        public Collection<Course> Prerequisites { get; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    目的是调用者可以通过修改集合来改变课程的先决条件.在这种情况下,如果我们使用List<Course>,则Course在先决条件发生变化时无法通知类,因为List<T>不提供任何修改回调.因此,List<T>在这种情况下使用就像拥有任意多个公共字段一样.另一方面,我们可以子类化Collection<T>并覆盖其虚拟以通知更改.

List<T>当集合的完整所有权转移给调用者时,最适合作为返回值.这就是为什么Enumerable.ToList()它实际上是完全合理的,它并没有违反规则的精神.

现在我考虑一下,允许List<T>作为方法的返回值,但继续标记List<T>属性和参数可能会大大提高规则的信噪比......