156

参见System.Array类的定义

public abstract class Array : IList, ...

理论上我应该能写到这点并且开心

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

我也应该能够从 iList 调用任何方法

 ilist.Add(1); //exception here

我的问题不是为什么我得到一个异常,而是为什么 Array 实现 IList

4

7 回答 7

104

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

集合也没有只读接口。而且我缺少的不仅仅是带有索引器界面的恒定大小。

IMO 应该有更多(通用)集合接口,具体取决于集合的功能。名称也应该不同,List因为带有索引器的东西真的很愚蠢 IMO。

  • 只是枚举IEnumerable<T>
  • 只读但没有索引器(.Count、.Contains、...)
  • 可调整大小但没有索引器,即设置为 (Add, Remove,...) currentICollection<T>
  • 带索引器的只读 (indexer, indexof,...)
  • 带索引器的恒定大小(带设置器的索引器)
  • 具有索引器(插入,...)电流的可变大小IList<T>

我认为当前的集合界面设计不佳。但是因为它们有属性告诉你哪些方法是有效的(这是这些方法契约的一部分),它不会违反替换原则。

于 2011-05-11T18:22:47.827 回答
43

文档的备注部分IList说:

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

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

于 2011-05-11T18:23:21.600 回答
17

因为并非所有IList的 s 都是可变的(参见IList.IsFixedSizeIList.IsReadOnly),并且数组的行为当然类似于固定大小的列表。

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

于 2011-05-11T18:24:03.307 回答
5

这是我们从不清楚如何处理只读集合以及 Array 是否为只读的时代遗留下来的。IList 接口中有 IsFixedSize 和 IsReadOnly 标志。IsReadOnly 标志表示完全不能更改集合,而 IsFixedSize 表示集合确实允许修改,但不允许添加或删除项目。

在 .Net 4.5 的时候,很明显需要一些“中间”接口来处理只读集合,因此IReadOnlyCollection<T>引入IReadOnlyList<T>了。

这是一篇描述详细信息的精彩博客文章:Read only collections in .NET

于 2014-11-22T14:40:11.060 回答
0

IList 接口的定义是“表示可以通过索引单独访问的对象的非泛型集合。”。数组完全满足这个定义,所以必须实现接口。调用 Add() 方法时的异常是“System.NotSupportedException:Collection was a fixed size”并且由于数组无法动态增加其容量而发生。它的容量是在创建数组对象时定义的。

于 2011-05-11T18:30:48.390 回答
0

让数组实现 IList(以及可传递的 ICollection)简化了 Linq2Objects 引擎,因为将 IEnumerable 转换为 IList/ICollection 也适用于数组。

例如,Count() 最终会在后台调用 Array.Length,因为它被强制转换为 ICollection 并且数组的实现返回 Length。

如果没有这个,Linq2Objects 引擎将不会对数组进行特殊处理并且性能会很糟糕,或者他们需要将代码加倍,为数组添加特殊情况处理(就像他们为 IList 所做的那样)。他们一定选择让数组实现 IList。

这就是我对“为什么”的看法。

于 2020-02-14T10:59:21.430 回答
0

还有实现细节 LINQ Last 检查 IList ,如果它没有实现 list 他们将需要 2 次检查减慢所有 Last 调用或 Last 上的 Array 采用 O(N)

于 2020-04-08T03:41:39.577 回答