我认为这个问题是自我解释的。我宁愿把更多的注意力放在支持问题的例子上。
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
public interface ICollection : IEnumerable
{
void CopyTo(Array array, int index);
int Count { get; }
Object SyncRoot { get; }
bool IsSynchronized { get; }
}
public interface IList : ICollection
{
Object this[int index] { get; set; }
int Add(Object value);
bool Contains(Object value);
void Clear();
bool IsReadOnly { get; }
bool IsFixedSize { get; }
int IndexOf(Object value);
void Insert(int index, Object value);
void Remove(Object value);
void RemoveAt(int index);
}
很明显,IEnumerable
是独立的,只允许循环集合。但我不明白为什么他们将ICollection
和IList
分开?即使它们是一个,IList也不会变胖,因为任何集合都需要这种行为?
我发现了this帖子,其中说如果客户端只需要循环项目,IEnumerable
,如果只需要只读访问权限,那么您的API将返回ICollection
,等等。< / p>
MSFT如何完美地应用ISP,这些年来从未引起任何问题?
是否根据客户端代码需求或一次性应用程序向ISP申请持续流程?如果ISP只应用一次,那么我的问题就在帖子标题中。
答案 0 :(得分:2)
我不明白为什么他们将
ICollection
和IList
分开?
IList
是一个集合,通过索引获取项目具有逻辑意义。将其分离成子接口是为了认识到存在其他索引未定义的集合的事实。 ISet
就是此类收集的一个例子。
合并ICollection
和IList
会对一个人以干净的方式定义ISet
的能力产生负面影响,因为必须实施这四种方法:
this[int index]
int IndexOf(Object value)
void Insert(int index, Object value)
void RemoveAt(int index)
另一方面,人们可以合理地论证方法
int Add(Object value);
bool Contains(Object value);
void Clear();
bool IsReadOnly { get; }
bool IsFixedSize { get; }
void Remove(Object value);
可能属于ICollection
界面。
接口隔离原则 - 如何决定隔离什么?
当课程到位时,回想起来决定分离什么的任务要容易得多。查看是否需要任何类来抛出未实现的异常。这些方法是移动到需要引入的子接口的主要候选者。
例如,考虑开始使用IList
方法移入ICollection
,而不是IList
子接口的设计。您可以使用这两个接口成功构建List
和LinkedList
类。
现在考虑在混合中添加HashSet
。这个类必须使用set集合实现四个不合适的方法,这表明你应该考虑添加一个或两个子接口 - 一个用于列表,另一个用于集合。
在你有任何类之前决定隔离是很困难的,因为你的界面往往满足需要使用它的特定类的需要。从平面接口结构开始并通过后续版本中的重构扩展它并不罕见。