代码如下所示:
namespace Test { public interface IMyClass { List<IMyClass> GetList(); } public class MyClass : IMyClass { public List<IMyClass> GetList() { return new List<IMyClass>(); } } }
当我运行代码分析时,我得到以下建议。
警告 3 CA1002:Microsoft.Design:将“IMyClass.GetList()”中的“List”更改为使用 Collection、ReadOnlyCollection 或 KeyedCollection
我应该如何解决这个问题,这里有什么好的做法?
要回答关于为什么不的问题的“为什么”部分List<T>,原因是面向未来和 API 的简单性。
List<T>
面向未来
List<T>没有被设计成通过子类化来轻松扩展;它旨在快速用于内部实现。你会注意到它上面的方法不是虚拟的,因此不能被覆盖,并且它的 // 操作中Add没有钩子Insert。Remove
Add
Insert
Remove
这意味着如果您将来需要更改集合的行为(例如拒绝人们尝试添加的空对象,或者在发生这种情况时执行额外的工作,例如更新您的类状态),那么您需要更改类型集合返回到一个可以子类化的集合,这将是一个破坏性的接口更改(当然,更改诸如不允许 null 之类的语义也可能是接口更改,但诸如更新内部类状态之类的事情不会)。
因此,通过返回可以轻松子类化的类Collection<T>或接口IList<T>,ICollection<T>或者IEnumerable<T>您可以将内部实现更改为不同的集合类型以满足您的需求,而不会破坏消费者的代码,因为它仍然可以返回为他们期望的类型。
Collection<T>
IList<T>
ICollection<T>
IEnumerable<T>
API 简单性
List<T>包含很多有用的操作,例如BinarySearch,Sort等等。但是,如果这是您要公开的集合,那么您很可能控制列表的语义,而不是消费者。因此,虽然您的班级内部可能需要这些操作,但您班级的消费者不太可能想要(甚至应该)调用它们。
BinarySearch
Sort
因此,通过提供更简单的集合类或接口,您可以减少 API 用户看到的成员数量,并使他们更易于使用。