请参阅 System.Array 类
的定义public abstract class Array : IList, ...
理论上,我应该能够写下这一点并且开心
int[] list = new int[] {};
IList iList = (IList)list;
我也应该可以从iList中调用任何方法
ilist.Add(1); //exception here
我的问题不是为什么我得到一个例外,而是为什么Array实现IList ?
答案 0 :(得分:89)
因为数组允许通过索引快速访问,IList
/ IList<T>
是唯一支持此功能的集合接口。所以也许你真正的问题是“为什么没有用于索引器的常量集合的接口?”对此我没有答案。
也没有集合的只读接口。而且我还缺少那些带有索引器界面的常量大小。
IMO应该有几个(通用)集合接口,具体取决于集合的功能。并且名称应该也不同,List
对于带有索引器的东西来说真是愚蠢的IMO。
IEnumerable<T>
ICollection<T>
IList<T>
我认为当前的集合接口是糟糕的设计。但由于它们具有告诉您哪些方法有效的属性(这是这些方法的合同的一部分),因此它不会破坏替换原则。
答案 1 :(得分:38)
IList
{{1}}的评论部分说
IList是该家族的后裔 ICollection接口是基础 所有非通用列表的接口。 IList实现分为三个 类别:只读,固定大小和 可变大小的即可。只读IList 无法修改。固定大小的IList 不允许添加或删除 元素,但它允许 修改现有元素。一个 可变大小的IList允许 添加,删除和修改 元件。
显然,数组属于固定大小的类别,因此通过界面的定义,它是有意义的。
答案 2 :(得分:17)
因为并非所有IList
都是可变的(请参阅IList.IsFixedSize
和IList.IsReadOnly
),并且数组的行为肯定与固定大小的列表相同。
如果您的问题确实是“为什么它实现了非通用接口”,那么答案就是这些问题在仿制药出现之前就已存在。
答案 3 :(得分:4)
这是我们从那时尚未清楚如何处理只读集合以及Array是否只读的时代的遗产。 IList接口中有IsFixedSize和IsReadOnly标志。 IsReadOnly标志意味着集合根本无法更改,IsFixedSize意味着集合允许修改,但不允许添加或删除项目。
在.Net 4.5时,很明显有些&#34;中间&#34;接口需要与只读集合一起使用,因此引入了IReadOnlyCollection<T>
和IReadOnlyList<T>
。
这是一篇很棒的博客文章,描述了详细信息:Read only collections in .NET
答案 4 :(得分:0)
IList接口的定义是“表示可以通过索引单独访问的非泛型对象集合”。数组完全满足此定义,因此必须实现接口。 调用Add()方法的异常是“System.NotSupportedException:Collection具有固定大小”并且因为数组无法动态增加其容量而发生。它的容量是在创建数组对象时定义的。
答案 5 :(得分:0)
具有数组实现IList(以及可传递的ICollection)简化了Linq2Objects引擎,因为将IEnumerable强制转换为IList / ICollection也适用于数组。
例如,一个Count()最终调用了Array.Length,因为它被强制转换为ICollection并且该数组的实现返回Length。
没有这些,Linq2Objects引擎将不会对数组进行特殊处理并表现出可怕的效果,或者它们需要加倍对数组添加特殊情况处理的代码(就像对IList所做的那样)。他们必须选择使数组实现IList。
这就是我对“为什么”的看法。
答案 6 :(得分:0)
实现细节LINQ Last检查IList,如果它没有实现list,他们将需要进行2次检查以减慢所有Last调用的速度,或者需要将Last放在具有O(N)的数组上