Подтвердить что ты не робот

Как массивы реализуют IList <T> без реализации свойства "Count" в С#?

В течение очень долгого времени мне было интересно узнать следующее:

int[] array = new int[1];
int iArrayLength = array.Length;    //1

Поскольку массивы реализуют интерфейс IList, допускается следующее:

int iArrayCount = ((IList<int>)array).Count;    //still 1

НО:

int iArrayCount = array.Count;  //Compile error. WHY?
int iArrayLength = array.Length;    //This is what we learned at school!

Вопрос: Как массив может реализовать IList<T> (особенно свойство int Count { get; } из IList<T>), не допуская его использования в базовом классе?

4b9b3361

Ответ 1

Это известно как реализация явного интерфейса. Элемент интерфейса не отображается как открытый элемент этого типа, но он доступен путем литья ссылки на тип интерфейса.

Это можно сделать в С# следующим образом:

interface I
{
    void M();
}

class C : I
{
    public int P { get; set; }
    void I.M() { Console.WriteLine("M!"); }
}

Затем вы можете использовать эти типы следующим образом:

C obj = new C();
obj.P = 3;
((I)obj).M();

Но это не скомпилируется:

obj.M();

Как отмечает JeffN825, одной из причин для экспликации членов интерфейса является то, что они не поддерживаются типом. Например, Add выдает исключение (соответствующее обсуждение). Еще одна причина для экспликации члена заключается в том, что он дублирует другой открытый член с другим именем. То, что причина Count реализована явно; соответствующий публичный член Length. Наконец, некоторые члены реализуются неявно, а именно, индексатор. Обе эти линии работают (при условии, что arr представляет собой массив int):

arr[0] = 8;
((IList<int>)arr)[0] = 8;

Ответ 2

Поскольку массив не поддерживает все функции IList (Add/Remove/etc), IList.Count(и несколько других методов) реализуются в частном порядке (явно). Вы можете увидеть это при разборке:

int ICollection.Count

Если вы действительно хотели использовать Count, вы могли бы сделать

((IList)myArray).Count