关于c#:为什么数组实现了IList?

Why array implements IList?

参见System.Array类的定义

1
public abstract class Array : IList, ...

从理论上讲,我应该能够写下这一点并且感到快乐

1
2
int[] list = new int[] {};
IList iList = (IList)list;

我还应该能够从IList调用任何方法

1
 ilist.Add(1); //exception here

我的问题不是为什么我会得到一个异常,而是为什么数组实现了IList?


因为数组允许按索引快速访问,所以只有IList/IList是支持此功能的集合接口。因此,您真正的问题可能是"为什么没有索引器的常量集合接口?"对此我没有答案。

集合也没有只读接口。我甚至错过了一个比索引器接口更大的常量。

IMO根据集合的特性,应该有多个(通用)集合接口。而且名字也应该是不同的,在我看来,使用索引器的List是很愚蠢的。

  • 仅列举IEnumerable
  • 只读,但没有索引器(.count,.contains,…)
  • 可调整大小但没有索引器,即设置为(添加、删除等)当前ICollection
  • 使用索引器只读(indexer,indexof,…)
  • 带索引器的常量大小(带设置器的索引器)
  • 带索引器(insert,…)的可变大小当前IList

我认为当前的收集接口设计不好。但是,因为它们的属性告诉您哪些方法是有效的(这是这些方法的契约的一部分),所以不会破坏替换原则。


IList文件的备注部分说

IList is a descendant of the
ICollection interface and is the base
interface of all non-generic lists.
IList implementations fall into three
categories: read-only, fixed-size, and
variable-size. A read-only IList
cannot be modified. A fixed-size IList
does not allow the addition or removal
of elements, but it allows the
modification of existing elements. A
variable-size IList allows the
addition, removal, and modification of
elements.

显然,数组属于固定大小的类别,因此通过定义接口,它是有意义的。


因为并不是所有的IList都是可变的(见IList.IsFixedSizeIList.IsReadOnly),数组的行为肯定像固定大小的列表。

如果您的问题真的是"为什么它实现了一个非泛型接口",那么答案是,这些接口在泛型出现之前就已经存在了。


这是我们从不清楚如何处理只读集合以及数组是否为只读的时代留下的遗产。在IList接口中有isFixedSize和isReadOnly标志。isreadOnly标志表示集合根本无法更改,isFixedSize表示集合允许修改,但不允许添加或删除项。

在.NET 4.5时代,很明显需要一些"中间"接口来处理只读集合,因此引入了IReadOnlyCollectionIReadOnlyList

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


IList接口的定义是"表示可由索引单独访问的非通用对象集合"。数组完全满足这个定义,因此必须实现接口。调用add()方法时发生异常:"System.NotSupportedException:集合的大小固定",原因是数组无法动态增加其容量。它的容量是在创建数组对象期间定义的。