2011-01-22 1 views
9

Можно создать дубликат:
count vs length vs size in a collectionПочему массив C# не имеет свойства Count?

Действительно странно:

C# массивы, такие как следующую поддержку

double[] test = new double[1]; 

Имущество Длина, чтобы получить размер самого массив. Но массивы также реализуют интерфейс IList:

IList<double> list = test; 

Однако интерфейс IList также предоставляет свойство Count. Почему массив («тест» в этом случае) нет?

Редактировать: Спасибо всем, кто указал, что на самом деле это интерфейс ICollection (не IList), который предоставляет свойство Count, а также что это связано с явной реализацией интерфейса.

+2

... против ** Емкость ** ** против ItemCount ** (например, '' ColumnCount' в ListView' против 'Columns.Count') против ** количество_элементов ** (' 'NumIndices' в EnvDTE ') vs ** CountOfItems ** (' CountOfLines' в 'EnvDTE') и т. д. Я просто * люблю * согласованность в рамках MS. :) – Mehrdad

ответ

14

Просто они решили назвать его Length, а также осуществлять Count через явную реализацию интерфейса -что-то нравится:

int ICollection.Count { get { return Length; } } 
+2

+1 от меня, но я предполагаю, что они искали ответ на «почему»? – Mehrdad

+1

@mehrdad - Мне жаль, что у меня не было моей аннотированной спецификации :( –

+1

Спасибо, что указали мне на явные реализации интерфейса - понятия не имели, что такие вещи существуют ;-) – Chris

7

Это был выбор дизайна, касающийся названия, а не семантики.

Массивы имеют Длина свойство, равно как и строка.

Длина сигналы неизменяемые: вы не можете добавить или удалить из массива.

В списках и других контейнерах имеется Количество Недвижимость, которая может быть изменена.

О, и если вы вызываете list.Append(1.1);, вы получите исключение, которое не поддерживается.

+10

Длина отнюдь не сигнализирует неизменяемость; 'MemoryStream' (на самом деле, множество реализаций потока),' StringBuilder' и т. Д. –

+0

@Marc: Я не хотел подразумевать строгое правило. Потоки - это еще один домен, и я думаю, что StringBuilder.Length - это уступка String. Я все еще думаю, что он свободно держится за контейнеры. –

4

Типы наследования от Arrayobtain implementations of IList<T> at run-time (как это возможно, не спрашивайте меня):

В .NET Framework версии 2.0, Array класс реализует System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T>, и System.Collections.Generic.IEnumerable<T> общие интерфейсы. Реализации предоставляются в массивы во время выполнения и, следовательно, не являются видны в документации по строительству инструментов. В результате, общие интерфейсы не отображаются в синтаксисе декларации для класса Array , и нет никаких ссылок темы для членов интерфейса, которые доступных только литья массива для общего типа интерфейса (явной реализация интерфейса).Ключ вещь, о которой следует помнить, когда вы делаете массив на один из этих интерфейсов, - это , что элементы, которые добавляют, вставляют или удаляют элементы throw NotSupportedException.

В действительности IList<T> реализация действует как explicit implementation, так как Marc explained в своем ответе. Вот почему вы можете получить доступ к определенным членам IList<T> из результата броска, но не от переменной, типизированной как T[].

+0

Эта последняя строка была по существу уже в вопросе. –

+0

@ Хенк: Ты прав; Я хотел выделить часть «явной реализации»; включая пример кода, был излишним и только отвлекался от этой точки. Я удалил его. –

3

Свойство Count скрыто с помощью явного интерфейса декларации стиля, например, как это в определении класса:

int IList.Count { 
    get { 
     // ...etc... 
    } 
} 

Вы можете получить доступ к методам и свойствам, скрытым, как это, используя приведение типа, например,

((IList<double>) myArray).Count 
+4

IList фактически не определяет Count; ICollection делает –

+0

@Marc: Способ, которым наследует интерфейс, делает это довольно спорным. –

+0

@Henk - Мне нужно будет проверить, но делает ли это * скомпилировать *, если вы ошибаетесь? Я не думаю, что так ... –