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

时间:2016-06-30 08:34:11

标签: c# list system.array

此代码:

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

投掷Build:

  

错误CS1061:' System.Array'不包含'添加'的定义没有扩展方法'添加'接受类型' System.Array'的第一个参数。可以找到(你错过了使用指令或程序集引用吗?)

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

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

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

7 个答案:

答案 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的原因。

供参考:Why array implements 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并在NotSupportedExceptionAddInsertRemove方法中抛出RemoveAt