11

这段代码:

int[] myArr = { 1, 2 };
myArr.Add(3);

在构建时引发以下错误:

错误 CS1061:“System.Array”不包含“Add”的定义,并且找不到接受“System.Array”类型的第一个参数的扩展方法“Add”(您是否缺少 using 指令或程序集引用? )

IList接口有Add()方法,为什么Array没有实现呢?

更新:我从答案中看到它确实明确地实现了它,好的,我明白了,谢谢,我最好坚持这个问题:

为什么Array实际上不提供 Add(),或者,更好,为什么它必须IList首先实施?而不是实现IList,它可能是另一个接口(例如IArray),它可能只对IList-eg的 Array 成员有用IsFixedSizeIsReadOnly...IndexOf()只是一个想法。

4

7 回答 7

11

为什么 Array 实际上不提供 Add()?

数组具有固定大小,因此您无法添加新元素。

维数和每个维的长度是在创建数组实例时建立的。在实例的生命周期内无法更改这些值。 https://msdn.microsoft.com/en-us/library/9b9dty7d.aspx

为什么它必须首先实现 IList?

IList 的定义:表示可以通过索引单独访问的非泛型对象集合。

https://msdn.microsoft.com/en-us/library/system.collections.ilist.aspx

Array 是通过索引访问的,而 IList 容纳了这个索引,这就是 Array 实现 IList 的原因。

供参考:为什么数组实现 IList?

于 2016-06-30T08:37:17.220 回答
9

System.Array是的,如果已经实现IReadOnlyList或类似的接口,它似乎应该是一个更好的设计。但是,IReadOnlyList<T>出现在.Net 4.5中,而System.Array保留在最初的.Net 1.0中。微软,恕我直言,尽力而为,并通过 显式接口实现隐藏 Add

http://referencesource.microsoft.com/#mscorlib/system/array.cs,156e066ecc4ccedf

  ...
int IList.Add(Object value)
{
    throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
} 
  ...

所以你不能做

int[] myArr = { 1, 2 };

myArr.Add(3);

但你可以坚持使用Add(并被NotSupportedException抛出)通过

((IList) myArr).Add(3);

甚至

if (!myArr.IsFixedSize) {
  // we have very strange array, let's try adding a value to it
  ((IList) myArr).Add(3);
}
于 2016-06-30T09:02:56.623 回答
3

它确实提供了 Add,但是通过抛出一个NotSupportedException(参见MSDN),因为数组的大小是固定的。

相反,您收到编译错误的原因是因为接口是显式实现的,所以如果您想调用需要强制转换为IList. 请参阅有关显式接口实现的 C# 指南。

于 2016-06-30T08:39:10.010 回答
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会抛出 a ,因为数组具有固定大小,并且您不能向数组添加新元素,因为它的大小是在初始化时确定的 ( new int[0])。

于 2016-06-30T08:42:07.950 回答
2

System.Array 类实现 IList 但不提供 Add()

当然它是通过显式实现来实现的(没有办法实现接口而不实现某些成员)。

为什么数组实现IList

嗯,主要是说明它支持indexer。

但实际上数组实现了一种有效的IList用法。该IList接口有一个名为 的属性IsFixedSize,根据文档

获取一个值,该值指示 IList 是否具有固定大小。

接着

固定大小的集合在集合创建后不允许添加或删除元素,但允许修改现有元素。

所以数组实现在、和方法中返回和IsFixedSize = true抛出。NotSupportedExceptionAddInsertRemoveRemoveAt

于 2016-06-30T09:00:50.117 回答
1

根据msdn:

IList.Add(对象)

调用此方法总是会引发 NotSupportedExceptionexception。

数组类- 见显式接口实现部分

Array有这个方法。要调用此方法,您应该显式转换为IList. 这个方法不能被调用,因为数组有固定的大小,这个大小不能动态改变。

于 2016-06-30T08:44:30.910 回答
1

IList在三个不同的类别中实现:

  • 只读
  • 可变尺寸
  • 固定尺寸

显然该Array类型是一个固定大小的实现IList。您无法Add()从 an 访问该方法的Array原因是该方法是显式实现的:

public class A : IList {
    public void IList.Add(object o){
         ...
    }
}

这意味着您需要将数组转换为 anIList才能使用该Add方法(即使它会引发不受支持的异常)。

你可能会说这是一个糟糕的设计,很多人会同意你的观点。

阅读有关明确定义的接口的更多信息: https ://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx

于 2016-06-30T08:45:27.047 回答