IEnumerable <T> по сравнению с T []

Я просто понимаю, что, возможно, ошибался все время в представлении T[] к моим представлениям, вместо IEnumerable<T>.

Обычно, для этого вида кода:

foreach (var item in items) {}

item должен быть T[] или IEnumerable<T>?

Чем, если я должен получить количество объектов, был бы Array.Count будьте быстрее по IEnumerable<T>.Count()?

21
задан stacker 8 August 2010 в 07:02
поделиться

7 ответов

IEnumerable , как правило, здесь лучше по причинам, указанным в другом месте. Однако я хочу поднять один момент по поводу Count () . Квинтин неправ, когда говорит, что тип сам по себе реализует Count () . Фактически он реализован в Enumerable.Count () как метод расширения, что означает, что другие типы не могут его переопределить для обеспечения более эффективных реализаций.

По умолчанию Count () должен перебирать всю последовательность для подсчета элементов. Однако он знает о ICollection и ICollection и оптимизирован для этих случаев. (В .NET 3.5 IIRC он оптимизирован только для ICollection .) Теперь массив реализует это , поэтому Enumerable.Count () подчиняется ICollection .Count и избегает итерации по всей последовательности.Это все равно будет немного медленнее, чем прямой вызов Length , потому что Count () должен обнаружить, что он для начала реализует ICollection - но на по крайней мере, это все еще O (1).

То же самое верно и для производительности в целом: код JITted может быть несколько более жестким при итерации по массиву, а не по общей последовательности. По сути, вы предоставили бы JIT больше информации для игры, и даже сам компилятор C # по-разному обрабатывает массивы для итераций (напрямую используя индексатор).

Однако эти различия в производительности будут несущественными для большинства приложений - я бы определенно выбрал более общий интерфейс, пока у меня не появится веская причина не делать этого.

31
ответ дан 29 November 2019 в 20:28
поделиться

Поскольку класс Array реализует System.Collections.Generic.IList , System.Collections.Generic.ICollection и System.Collections. Generic.IEnumerable общие интерфейсы, я бы использовал IEnumerable, если вам не нужно использовать эти интерфейсы.

http://msdn.microsoft.com/en-us/library/system.array.aspx

3
ответ дан 29 November 2019 в 20:28
поделиться

Это частично несущественно, но стандартная теория диктует: «Программа против интерфейса, а не реализации». С помощью модели интерфейса вы можете изменить фактический передаваемый тип данных, не затрагивая вызывающего, если он соответствует тому же интерфейсу.

В отличие от этого, у вас может быть причина специально раскрыть массив, и в этом случае вы захотите выразить это.

Для вашего примера, я думаю, было бы желательно IEnumerable . Также стоит отметить, что для целей тестирования использование интерфейса могло бы уменьшить количество головной боли, которую вы бы понесли, если бы у вас были определенные классы, которые вам приходилось бы постоянно воссоздавать, коллекции в целом не так плохи, но наличие контракта интерфейса вы можете легко издеваться, это очень приятно.

Добавлено для редактирования:
Это более несущественно, потому что базовый тип данных - это то, что будет реализовывать метод Count () , для массива он должен иметь доступ к известной длине, я бы не беспокоился ни о каких воспринимаемые накладные расходы метода. См. Ответ Джона Скита для объяснения реализации Count () .

5
ответ дан 29 November 2019 в 20:28
поделиться

T [] (один размер, с нуля) также реализует ICollection и IList с IEnumerable .

Поэтому, если вы хотите меньшего связывания в своем приложении, IEnumerable предпочтительнее. Если вам не нужен индексированный доступ внутри foreach .

3
ответ дан 29 November 2019 в 20:28
поделиться

По вашему мнению, если все представление, о котором заботится или должно заботиться, имеет перечислимое значение, это все, что оно должно требовать в своих интерфейсах.

1
ответ дан 29 November 2019 в 20:28
поделиться

Что это логически (концептуально) извне?

Если это массив, то вернуть массив. Если единственное, что нужно сделать - перечислить, верните IEnumerable. В противном случае IList или ICollection могут быть подходящим вариантом.

Если вы хотите предложить множество функций, но не позволяете их изменять, возможно, используйте List внутри и верните ReadonlyList, возвращенный из этого метода .AsReadOnly ().

0
ответ дан 29 November 2019 в 20:28
поделиться

Учитывая, что изменить код с массива на IEnumerable позже легко, а вот изменить его другим способом - нет, я бы выбрал IEnumerable, пока вы не узнаете, что вам нужна небольшая часть выгода от возврата массива.

0
ответ дан 29 November 2019 в 20:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: