C# 为什么System.Array类实现IList但不提供Add()
此代码:C# 为什么System.Array类实现IList但不提供Add(),c#,list,system.array,C#,List,System.array,此代码: int[] myArr = { 1, 2 }; myArr.Add(3); 在生成时引发以下错误: 错误CS1061:“System.Array”不包含“Add”的定义,并且找不到接受“System.Array”类型的第一个参数的扩展方法“Add”(是否缺少using指令或程序集引用?) IList接口有Add()方法,但是为什么数组没有实现它呢 更新:我从答案中看到它确实明确地实现了它,好的,我明白了,谢谢,我最好还是坚持这个问题: 为什么Array实际上没有提供Add(),或者更
int[] myArr = { 1, 2 };
myArr.Add(3);
在生成时引发以下错误:
错误CS1061:“System.Array”不包含“Add”的定义,并且找不到接受“System.Array”类型的第一个参数的扩展方法“Add”(是否缺少using指令或程序集引用?)
IList
接口有Add()
方法,但是为什么数组没有实现它呢
更新:我从答案中看到它确实明确地实现了它,好的,我明白了,谢谢,我最好还是坚持这个问题:
为什么
Array
实际上没有提供Add()
,或者更好的是,为什么它首先必须实现IList
?它可以是另一个接口(例如,IArray
),而不是实现IList
,该接口可能只具有对IList
的数组成员有用的属性-例如,IsFixedSize
,IsReadOnly
,IndexOf()
。。。只是想一想。为什么数组实际上不提供Add()?
数组具有固定大小,因此无法添加新元素
尺寸的数量和每个尺寸的长度如下所示
在创建阵列实例时建立。这些值不能被忽略
在实例的生存期内更改。
为什么首先必须实施IList?
IList的定义:表示对象的非泛型集合
可以通过索引单独访问的
数组由索引访问,IList容纳此索引,这就是数组实现IList的原因
仅供参考:它确实提供了Add,但是抛出了一个
NotSupportedException
(请参阅),因为数组的大小是固定的
相反,出现编译错误的原因是接口是显式实现的,因此如果要调用该方法,则需要强制转换到
IList
。请参阅本C#指南。尽管实现接口的类必须实现接口的所有成员,但它可以显式实现它们:
public class MyList<T> : IList<T>
{
// ... shortened for simplicity
void ICollection<T>.Add(T item) { } // explicit implementation
}
public class A : IList {
public void IList.Add(object o){
...
}
}
它将进行编译,但在运行时将抛出一个NotSupportedException
,因为数组具有固定大小,并且不能向数组中添加新元素,因为它的大小是在初始化时确定的(new int[0]
)。根据msdn:
添加(对象)
调用此方法始终会引发NotSupportedExceptionexception
-参见显式接口实现部分
数组
具有此方法。要调用此方法,应显式强制转换为IList
。无法调用此方法,因为数组具有固定大小,并且此大小不能动态更改。IList
在三个不同类别中实现:
- 只读
- 可变尺寸
- 固定尺寸
Array
类型是IList
的固定大小实现。
无法从数组访问Add()
方法的原因是该方法是显式实现的:
public class MyList<T> : IList<T>
{
// ... shortened for simplicity
void ICollection<T>.Add(T item) { } // explicit implementation
}
public class A : IList {
public void IList.Add(object o){
...
}
}
这意味着您需要将数组强制转换为IList
,然后才能使用Add
方法(即使它会引发不受支持的异常)
你可能会说这是一个糟糕的设计,很多人会同意你的观点
阅读有关显式定义接口的更多信息:
数组类实现IList,但不提供Add()
当然,它是通过显式实现实现的(无法实现接口,也无法实现某些成员)
阵列为何实现IList
那么主要是表示它支持indexer
但实际上,数组实现了一种有效的IList
用法。IList
接口有一个名为的属性,根据文档
获取一个值,该值指示IList是否具有固定大小
然后
具有固定大小的集合不允许在创建集合后添加或删除元素,但允许修改现有元素
因此,数组实现返回
IsFixedSize=true
并在Add
、Insert
、Remove
和RemoveAt
方法中抛出NotSupportedException
,如果System.Array
实现了IReadOnlyList
或类似的接口,那么它应该是一个更好的设计。但是,IReadOnlyList
出现在.net4.5中,而System.Array
保留在.net1.0的初始值。微软IMHO尽了最大努力,通过显式界面实现隐藏了Add
所以你不能这么做
int[] myArr = { 1, 2 };
myArr.Add(3);
但是您可以坚持使用Add
(并通过
甚至
if (!myArr.IsFixedSize) {
// we have very strange array, let's try adding a value to it
((IList) myArr).Add(3);
}
如果将其转换为
IList
,则可以调用Add
(类可以实现一些接口,这意味着您在将其视为该接口时只能访问(所有)接口方法)。不过你会失望的。数组有一个固定的大小。那么为什么该语言不从数组类签名中删除:IList呢?它没有。数组实现了IList
-但是如果你想将它用作IList
,你必须将它转换成那种类型的变量。@Damien_不信者,很抱歉我更正了这个问题,我的意思是为什么它不删除它!这回答了你的问题吗?那么为什么它要实现IList(它有Add)?@cnom您可以在这里看到:Add()
不是ICollection
@haim770的一部分是的:您是对的。我提到了非泛型版本,它(明确地)通过问题中的Array
实现
((IList) myArr).Add(3);
if (!myArr.IsFixedSize) {
// we have very strange array, let's try adding a value to it
((IList) myArr).Add(3);
}