为什么不能在数组上调用RemoveAt?

时间:2018-09-26 15:06:51

标签: c# arrays compiler-errors

现在,我知道在C#中,数组是固定大小的集合。不能对它们使用except that the System.Array class, which all array types extend from, implements the System.Collections.IList interfaceRemoveAt方法是有道理的,它需要使用RemoveAt方法。

如果为you upcast an array to an IList, or pass it to a method taking an IList as an argument,则可以在其上调用.RemoveAt,这将在运行时抛出NotSupportedException。但是,如果我上载它,and call it directly,尽管方法明确存在,但会导致编译器错误'int[]' does not contain a definition for 'RemoveAt'

什么允许编译器在编译时捕获此NotSupportedException?它是数组的特例,还是我可以定义自己的类来具有这种行为?

2 个答案:

答案 0 :(得分:3)

数组实际上不应该实现IList,因为它没有完全实现该接口,因此不是NotSupportedException,但为方便起见添加了它。

调用Array.RemoveAt时无法编译的原因是因为Array实现了IList explicitly的方法,这意味着该方法除非将其强制转换为该接口,否则不可用。

这看起来像:

class OnlySortOfAList : IList
{
  void IList.RemoveAt(int Index) // note the lack of access modifier
  {
    throw new NotSupportedException();
  }
}

答案 1 :(得分:0)

某些类型的数字索引集合可以调整大小,而有些则不能。如果.NET为可调整大小的集合和不可调整大小的集合使用了单独的接口,则不可能编写单个包装器类来允许客户端调整包装后的集合的大小,但仍可用于不支持调整大小的集合。如果代码需要包装一些不支持调整大小的集合,但又需要调整一些不支持大小调整的集合,则必须为每种目的编写单独的包装器类。

如果代码具有数组类型的引用,则编译器将通过该类型的引用知道该类型可以使用或不使用哪些方法。永远无法有效处理某个方法的类通常不会通过其自身类型的引用公开它,因为代码没有理由在该类型的引用上调用这种方法。但是,如果一个类实现了一个接口,则它必须考虑到外部代码可能会调用无用方法的可能性,而外部代码并没有意识到那些方法是无用的,因此必须为接口中的每个方法都包括某种代码。 / p>

尽管处理接口的实际机制有所不同,但认为接口函数具有特殊名称可能会很有用,因此,如果类Woozle实现了包含方法Foo()的接口IWoozle并使用其自己的函数Foo()隐式实现该接口,它将实际上包含两个方法:public void Foo();public void IWoozle▪Foo() { Foo(); } // Not the actual name

如果类Zoozle显式实现IWoozle.Foo,则它将仅实现后一种方法。在给定Woozle x; Zoozle y;的情况下,给定x.Foo()y.Foo()的编译器将寻找一个名为Foo()的方法(Woozle有,但Zoozle没有) )。给定IWoozle x1=x, y1=y;,给定x1.Foo()y1.Foo()的编译器将查找IWoozle▪Foo,它将在xy中找到。