【问题标题】:Why can't I call RemoveAt on an array?为什么我不能在数组上调用 RemoveAt?
【发布时间】:2019-03-02 10:05:00
【问题描述】:

现在,我知道在 C# 中,数组是一个固定大小的集合。你不能对它们使用RemoveAt 方法是有道理的,except that the System.Array class, which all array types extend from, implements the System.Collections.IList interface,这需要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?它是数组的特殊情况,还是我可以定义自己的类来具有这种行为?

【问题讨论】:

标签: c# arrays compiler-errors


【解决方案1】:

Array 确实不应该实现 IList,因为它没有完全实现该接口,因此出现 NotSupportedException,但可能是为了方便而添加的。

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

这看起来像:

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

【讨论】:

  • 如果数组没有实现IList,那么就不可能有一个可以同时包装T[]IList<T>的类(例如,为了在元素被修改时触发事件),但支持在包装支持此类功能的集合时添加/删除元素的功能。虽然IList<T> 缺乏足够的方法来报告实现可以或不能做的事情,但是能够编写一个可以处理“厨房水槽”接口的所有“部分”实现的包装器比必须编写一个单独的包装器类更干净每个功能组合。
【解决方案2】:

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

如果代码具有数组类型的引用,编译器将知道该类型通过该类型的引用公开和不公开哪些方法。永远无法有效处理某个方法的类通常不会通过它们自己类型的引用来公开它,因为代码没有理由在该类型的引用上调用这样的方法。然而,如果一个类实现了一个接口,它必须考虑到无用的方法可能被没有意识到这些方法是无用的外部代码调用的可能性,因此必须为接口中的每个方法包含某种代码。

虽然处理接口的实际机制不同,但将接口函数视为具有特殊名称可能会很有用,因此如果类 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 中找到。

【讨论】:

    猜你喜欢
    • 2017-06-26
    • 2010-11-28
    • 2013-01-17
    • 1970-01-01
    • 2017-10-14
    • 2011-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多