查看System.Array类的定义。
public abstract class Array : IList, ...
从理论上讲,我应该能够编写这一部分并感到满意
int[] list = new int[] {};
IList iList = (IList)list;
我也应该能够从 iList 调用任何方法。
ilist.Add(1); //exception here
我的问题不是为什么我会得到一个异常,而是为什么数组实现了IList接口?
查看System.Array类的定义。
public abstract class Array : IList, ...
从理论上讲,我应该能够编写这一部分并感到满意
int[] list = new int[] {};
IList iList = (IList)list;
我也应该能够从 iList 调用任何方法。
ilist.Add(1); //exception here
我的问题不是为什么我会得到一个异常,而是为什么数组实现了IList接口?
IList
/IList<T>
支持此操作。因此,也许你真正的问题是“为什么没有支持索引器的常量集合接口?”对此我没有答案。
同时,也没有适用于集合的只读接口。我比缺少常量大小索引器接口更加需要这些只读接口。
在我看来,应该根据集合特性添加多个(通用)集合接口。这些接口的名称也应该不同,例如,使用索引器的列表称为List
实在太愚蠢了。
IEnumerable<T>
ICollection<T>
IList<T>
我认为当前的集合接口设计很糟糕。但由于它们具有告诉您哪些方法是有效的属性(这是这些方法契约的一部分),因此它不会破坏代换原则。
add
,因此在需要此功能时不能替换为具有此能力的内容。 - Rune FSIsFixedSize
和IsReadOnly
属性,但它明显违反了“告诉,不要问原则”和“最小惊讶原则”。当您打算对9个方法中的4个抛出异常时,为什么要实现接口呢? - MatthewIList 是ICollection接口的后代,并且是所有非泛型列表的基本接口。 IList 实现可以分为三种类别:只读、固定大小和可变大小。 只读 IList 不能被修改。 固定大小的 IList 不允许添加或删除元素,但允许修改现有元素。 可变大小的 IList 允许添加、删除和修改元素。
很明显,数组属于固定大小的范畴,因此根据该接口的定义是有意义的。
Array
,它确实显式实现了 Add
方法,这降低了意外调用它的风险。 - Brian RasmussenIList
实现,那么文档就不再正确了。 :P - Timo因为并非所有的IList
都是可变的(请参见IList.IsFixedSize
和IList.IsReadOnly
),而数组确实像固定大小的列表一样运作。
如果你真正想问的是“为什么它要实现一个非泛型接口”,那么答案是在泛型出现之前就存在了。
IList
本身就告诉你它可能不可变。如果它确实保证是可变的,而数组告诉你它不是,那么才会违反规则。 - user541686IList<T>
的情况下,数组确实会破坏 LSP,而在非泛型 IList
的情况下不会破坏它:http://enterprisecraftsmanship.com/2014/11/22/read-only-collections-and-lsp/ - VladimirIList
并检查。不过你应该在一个单独的问题中问这个。 - user541686此外,LINQ 的实现细节为 IList 进行了最后的检查,如果它没有实现 list,则需要进行两个检查来减慢所有 Last 调用,或者在数组上使用 O(N) 的 Last。
IList接口的定义是“表示一组非泛型对象,可以通过索引单独访问”。数组完全满足这个定义,因此必须实现该接口。 调用Add()方法时出现异常:“System.NotSupportedException:集合大小固定”,这是因为数组无法动态增加其容量。其容量在创建数组对象时被定义。
将数组实现IList(以及传递地,ICollection)简化了Linq2Objects引擎,因为将IEnumerable转换为IList / ICollection也适用于数组。
例如,Count()最终调用Array.Length,因为它被强制转换为ICollection并且数组的实现返回Length。
如果没有这个,Linq2Objects引擎将不会对数组进行特殊处理,并表现得非常糟糕,或者他们需要加倍的代码来添加数组的特殊情况处理(就像他们为IList所做的那样)。他们必须选择使数组实现IList。
这是我的看法。
Array
只是 IList
的许多可能实现之一。
由于代码应该松散耦合,依赖于抽象等等... 使用连续内存(数组)来存储其值的 IList
的具体实现称为 Array
。我们不会将 IList
添加到 Array
类中,这只是错误的推理顺序;Array
作为数组实现了 IList
。
异常正是接口定义的内容。如果您知道整个接口而不仅仅是单个方法,则不会感到惊讶。接口还提供了检查 IsFixedSize
属性并查看是否可以安全调用 Add
方法的机会。