为什么数组实现IList?

ole*_*sii 137 c# arrays ilist liskov-substitution-principle

请参阅System.Array类的定义

public abstract class Array : IList, ...
Run Code Online (Sandbox Code Playgroud)

从理论上讲,我应该能够写下这一点,并感到高兴

int[] list = new int[] {};
IList iList = (IList)list;
Run Code Online (Sandbox Code Playgroud)

我也应该可以从iList中调用任何方法

 ilist.Add(1); //exception here
Run Code Online (Sandbox Code Playgroud)

我的问题不是为什么我得到一个例外,而是为什么Array实现了IList

Cod*_*aos 91

因为数组允许通过索引快速访问,所以IList/ IList<T>是唯一支持它的集合接口.所以也许你真正的问题是"为什么没有用于索引器的常量集合的接口?" 对此我没有答案.

集合也没有只读接口.而且我还缺少那些与索引器接口不变的常数.

IMO应该有几个(通用)集合接口,具体取决于集合的功能.而名称也应该有所不同,List因为索引器的东西真是愚蠢的IMO.

  • 只是枚举 IEnumerable<T>
  • 只读但没有索引器(.Count,.Contains,...)
  • 可调整大小但没有索引器,即设置为(添加,删除,...)当前 ICollection<T>
  • readonly with indexer(indexer,indexof,...)
  • 带索引器的常量大小(带有setter的索引器)
  • 索引器(插入,...)当前的可变大小 IList<T>

我认为当前的集合接口是糟糕的设计.但由于它们具有告诉您哪些方法有效的属性(这是这些方法的合同的一部分),因此它不会破坏替换原则.

  • 它确实打破了LSP.如果它没有list.Add(item)应该将项添加到列表中,而不管具体类型如何.除例外情况.在数组实现中,在非异常情况下抛出异常,这本身就是不好的做法 (15认同)
  • 谢谢你的回答.但我宁愿把问题保留原样.原因很简单.接口是一个公共合同.如果实现它,必须完全实现所有成员,否则它会破坏LSP并且通常闻起来很糟糕,不是吗? (14认同)
  • 原始问题已经过了一段时间.但现在使用.Net 4.5,还有其他接口[IReadOnlyList](https://msdn.microsoft.com/en-us/library/hh192385.aspx)和[IReadOnlyCollection](https://msdn.microsoft.com/ EN-US /库/ hh881542.aspx). (11认同)
  • 我承认它*技术上*不违反LSP*只是因为*文档声明你应该检查`IsFixedSize`和`IsReadOnly`属性,它肯定违反了*Tell,Do not Ask原则*和*最少惊喜的原则*.为什么要在9种方法中为4种方法抛出异常时实现接口? (6认同)
  • @smelch我很抱歉,但你错了LSP.数组不实现`add`,因此不能替代在需要该功能时执行的操作. (2认同)

Bri*_*sen 40

在的备注部分文档IList

IList是ICollection接口的后代,是所有非泛型列表的基本接口. IList实现分为三类:只读,固定大小和可变大小.无法修改只读IList.固定大小的IList不允许添加或删除元素,但它允许修改现有元素.可变大小的IList允许添加,删除和修改元素.

显然,数组属于固定大小的类别,因此通过界面的定义,它是有意义的.

  • 从文档的角度来看,这实际上是一个很好的答案.但对我来说,它看起来像一个黑客.接口必须简洁和简单,以便类实现所有成员. (8认同)
  • 我猜他们最终会有很多接口.IListFixedSize,IListReadOnly ...... (4认同)
  • @Magnus - 在.Net 4.5中,还有其他接口 [IReadOnlyList](https://msdn.microsoft.com/en-us/library/hh192385.aspx?f=255&amp;MSPPError=-2147217396) 和 [IReadOnlyCollection](https: //msdn.microsoft.com/en-us/library/hh881542.aspx?f=255&amp;MSPPError=-2147217396)。 (2认同)

Meh*_*dad 17

因为并非所有ILists都是可变的(请参阅IList.IsFixedSizeIList.IsReadOnly),并且数组肯定表现得像固定大小的列表.

如果您的问题确实是"为什么它实现了非通用接口",那么答案就是这些问题出现在仿制药出现之前.

  • @oleksii:不,它不会破坏LSP,因为接口`IList`*本身*告诉你它可能不是可变的.如果它实际上保证是可变的并且数组告诉你,*那么*它将打破规则. (10认同)
  • 实际上,Array 在通用“IList&lt;T&gt;”的情况下确实会破坏 LSP,而在非通用“IList”的情况下不会破坏它:http://enterprisecraftsmanship.com/2014/11/22/read-only-集合和lsp/ (2认同)

Vla*_*mir 5

从不清楚如何处理只读集合以及Array是否为只读的时代开始,这就是我们的遗产。IList接口中有IsFixedSize和IsReadOnly标志。IsReadOnly标志意味着完全不能更改集合,而IsFixedSize意味着该集合允许修改,但不允许添加或删除项。

在.NET 4.5的时候,很明显,一些“中间”的接口都需要工作,只读集合,因此IReadOnlyCollection<T>IReadOnlyList<T>进行了介绍。

这是一篇很棒的博客文章,描述了详细信息:.NET中的只读集合