为什么数组实现了IList接口?
为什么数组实现了IList?
数组允许通过索引进行快速访问,而IList/IList
同时,也没有用于集合的只读接口。我更加需要这些只读接口,比起带有索引器的常量大小的接口。
在我看来,应该有更多(泛型)集合接口,根据集合的功能来决定。而且,这些接口的名称也应该不同,List对于带有索引器的集合来说是非常愚蠢的。
- 仅遍历 IEnumerable
- 只读但没有索引器(.Count, .Contains,...)
- 可调整大小但没有索引器,例如(Add, Remove,...)当前的ICollection
- 只读带有索引器(indexer, indexof,...)
- 常量大小带有索引器(带有setter的索引器)
- 可变大小带有索引器(Insert,...)当前的IList
我认为目前的集合接口设计很糟糕。但是由于它们有属性告诉你哪些方法是有效的(这是这些方法的合同的一部分),所以它不会违反替代原则。
感谢你的回答。但我宁愿保留问题不变。原因很简单。接口是一个公共合同。如果一个类实现了接口,就必须完全实现所有成员,否则就会违反LSP原则,这通常是不好的,不是吗?
但是目前没有好的替代方案来替代IList
这确实违反了LSP。如果不违反LSP,list.Add(item)应该无论具体类型如何都会将item添加到列表中。除非有例外情况。在数组实现中,在非异常情况下会抛出异常,这本身就是不好的实践。
它不违反LSP,你只是使用方法不正确。在尝试修改对象之前,应该检查IsFixedSize或IsReadOnly。
对不起,但是你的理解是错误的。数组不实现add,因此当需要该功能时,它无法替代具有该功能的对象。
我承认,从技术上讲,它不违反LSP,只是因为文档中指出你应该检查IsFixedSize和IsReadOnly属性,但它绝对违反了“Tell, Don't Ask”原则和“最小惊讶原则”。为什么要实现一个接口,而在其中有4个方法会抛出异常呢?
一段时间过去了,但是现在在.NET 4.5中,有附加的接口IReadOnlyList和IReadOnlyCollection。
非常简单地说,这样做是为了避免破坏变更,否则人们会对此抱怨得更多。
如果检查IsReadonly或IsFixedSize,它就不会违反LSP,但会违反开放/封闭原则。在这里检查LSP:stackoverflow.com/questions/4428725/…
为什么数组实现了IList接口?
数组实现IList接口的原因是,不是所有的IList都是可变的,而数组确实表现得像固定大小的列表一样。如果您的问题实际上是“为什么它实现了一个非泛型的接口”,那么答案是在泛型出现之前,这些接口已经存在了。
不,它并没有违反LSP(Liskov Substitution Principle,里氏替换原则),因为接口IList本身告诉你它可能不可变。如果它确实保证是可变的,而数组告诉你它不是,那么才会违反这个规则。
实际上,在泛型IList
为什么数组实现了IList接口?
根据IList文档中的说明部分,我们可以得知IList是ICollection接口的子接口,也是所有非泛型列表的基础接口。IList的实现可以分为三个类别:只读、固定大小和可变大小。只读的IList不能被修改,固定大小的IList不允许添加或删除元素,但允许修改现有元素,而可变大小的IList允许添加、删除和修改元素。
很明显,数组属于固定大小的类别,所以从接口的定义上来看,数组实现IList是有意义的。
我猜他们最终会得到很多的接口,比如IListFixedSize、IListReadOnly等等,从文档的角度来看,这实际上是一个很好的答案。但对我来说,这看起来更像是一种破解方法。接口必须是简单的,以便类能够实现所有成员。
我同意。接口和运行时异常并不是最优雅的组合。为了Array的辩护,它确实显式地实现了Add方法,这降低了意外调用该方法的风险。
除非我们创建一个既禁止修改又禁止添加/删除的IList实现,那么文档将不再正确。
在.NET 4.5中,还有额外的接口IReadOnlyList和IReadOnlyCollection。但据我所知,遗憾的是没有相反的接口来排除不能被写入的集合。
除非你试图公开一个接口,以免强制要求具体实现。