此代码:
int[] myArr = { 1, 2 };
myArr.Add(3);
投掷Build:
错误CS1061:' System.Array'不包含'添加'的定义没有扩展方法'添加'接受类型' System.Array'的第一个参数。可以找到(你错过了使用指令或程序集引用吗?)
IList
接口有Add()
方法,但为什么Array没有实现呢?
更新:我从答案中看到它明确地实现了它,好吧,我明白了,谢谢你,我应该更好地坚持这个问题:
为什么Array
实际上提供 Add()
,或者更好,为什么它必须首先实现IList
?它不是实现IList
,而是另一个接口(例如IArray
),它只能对IList
-e.g的数组成员有用。 IsFixedSize
,IsReadOnly
,IndexOf()
......只是一个想法。
答案 0 :(得分:8)
为什么Array实际上不提供Add()?
数组具有固定大小,因此您无法添加新元素。
尺寸的数量和每个尺寸的长度 在创建数组实例时建立。这些值不可能 在实例的生命周期中更改。 https://msdn.microsoft.com/en-us/library/9b9dty7d.aspx
为什么必须首先实施IList?
IList的定义:表示非泛型对象集合 可以通过索引单独访问。
https://msdn.microsoft.com/en-us/library/system.collections.ilist.aspx
通过索引访问数组,IList适应此索引,这就是Array实现IList的原因。
答案 1 :(得分:6)
是的,如果System.Array
已实施IReadOnlyList
或类似界面,那么它似乎应该是更好的设计。但是,IReadOnlyList<T>
出现在 .Net 4.5 中,而System.Array
保留在最初的 .Net 1.0 中。微软,恕我直言,通过显式接口实现
http://referencesource.microsoft.com/#mscorlib/system/array.cs,156e066ecc4ccedf
Add
所以你做不到
...
int IList.Add(Object value)
{
throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
}
...
但您可以坚持使用int[] myArr = { 1, 2 };
myArr.Add(3);
(并通过<{p}}获取Add
NotSupportedException
甚至
((IList) myArr).Add(3);
答案 2 :(得分:3)
确实提供了Add,但是通过抛出NotSupportedException
(参见MSDN),因为数组的大小是固定的。
相反,您收到编译错误的原因是因为接口是显式实现的,因此如果要调用方法,则需要转换为IList
。请参阅此C#指南,了解explicit interface implementation。
答案 3 :(得分:3)
虽然实现接口的类必须实现接口的所有成员,但它可以显式实现它们:
public class MyList<T> : IList<T>
{
// ... shortened for simplicity
void ICollection<T>.Add(T item) { } // explicit implementation
}
如果您以这种方式实施该方法,它就不会在MyList<T>
的实例上显示:
MyList<int> list = new MyList<int>();
list.Add(5); // would NOT compile
((IList<int>)list).Add(5); // can be compiled
因此,如果您有int[]
,则可以执行此操作:
int[] array = new int[0];
((IList<int>)array).Add(5);
它将进行编译,但在运行时会抛出NotSupportedException
因为数组具有固定大小而您无法将新元素添加到数组中,因为它& #39;的大小是在初始化时确定的(new int[0]
)。
答案 4 :(得分:1)
根据msdn:
IList.Add(Object)
调用此方法始终会抛出NotSupportedExceptionexception。
Array Class - 参见显式接口实现部分
Array
有这种方法。要调用此方法,您应该明确转换为IList
。无法调用此方法,因为数组具有固定大小,并且无法动态更改此大小。
答案 5 :(得分:1)
IList
分为三个不同类别:
显然,Array
类型是IList
的固定大小实现。
您无法从Add()
访问Array
方法的原因是该方法已明确实施:
public class A : IList {
public void IList.Add(object o){
...
}
}
这意味着您需要先将数组转换为IList
,然后才能使用Add
方法(即使它会抛出一个不受支持的异常)。
你可能会说这是一个糟糕的设计,许多人会同意你的看法。
阅读有关明确定义的接口的更多信息: https://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx
答案 6 :(得分:1)
System.Array类实现IList但不提供Add()
当然它通过显式实现(没有办法实现接口而不实现某些成员)。
为什么数组实现了
IList
?
好吧,主要是为了表明它支持索引器。
但实际上数组实现了一个有效的IList
用法。 IList
接口有一个名为IsFixedSize
的属性,根据文档
获取一个值,该值指示IList是否具有固定大小。
然后
具有固定大小的集合在创建集合后不允许添加或删除元素,但它允许修改现有元素。
因此,数组实现返回IsFixedSize = true
并在NotSupportedException
,Add
,Insert
和Remove
方法中抛出RemoveAt
。