代码如下所示:
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()”中的“列表”更改为使用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用户看到的成员数量,并使他们更易于使用。