Я просто понимаю, что, возможно, ошибался все время в представлении T[]
к моим представлениям, вместо IEnumerable<T>
.
Обычно, для этого вида кода:
foreach (var item in items) {}
item
должен быть T[]
или IEnumerable<T>
?
Чем, если я должен получить количество объектов, был бы Array.Count
будьте быстрее по IEnumerable<T>.Count()
?
IEnumerable
, как правило, здесь лучше по причинам, указанным в другом месте. Однако я хочу поднять один момент по поводу Count ()
. Квинтин неправ, когда говорит, что тип сам по себе реализует Count ()
. Фактически он реализован в Enumerable.Count ()
как метод расширения, что означает, что другие типы не могут его переопределить для обеспечения более эффективных реализаций.
По умолчанию Count ()
должен перебирать всю последовательность для подсчета элементов. Однако он знает о ICollection
и ICollection
и оптимизирован для этих случаев. (В .NET 3.5 IIRC он оптимизирован только для ICollection
.) Теперь массив реализует это , поэтому Enumerable.Count ()
подчиняется ICollection
и избегает итерации по всей последовательности.Это все равно будет немного медленнее, чем прямой вызов Length
, потому что Count ()
должен обнаружить, что он для начала реализует ICollection
- но на по крайней мере, это все еще O (1).
То же самое верно и для производительности в целом: код JITted может быть несколько более жестким при итерации по массиву, а не по общей последовательности. По сути, вы предоставили бы JIT больше информации для игры, и даже сам компилятор C # по-разному обрабатывает массивы для итераций (напрямую используя индексатор).
Однако эти различия в производительности будут несущественными для большинства приложений - я бы определенно выбрал более общий интерфейс, пока у меня не появится веская причина не делать этого.
Поскольку класс Array реализует System.Collections.Generic.IList
, System.Collections.Generic.ICollection
и System.Collections. Generic.IEnumerable
общие интерфейсы, я бы использовал IEnumerable, если вам не нужно использовать эти интерфейсы.
Это частично несущественно, но стандартная теория диктует: «Программа против интерфейса, а не реализации». С помощью модели интерфейса вы можете изменить фактический передаваемый тип данных, не затрагивая вызывающего, если он соответствует тому же интерфейсу.
В отличие от этого, у вас может быть причина специально раскрыть массив, и в этом случае вы захотите выразить это.
Для вашего примера, я думаю, было бы желательно IEnumerable
. Также стоит отметить, что для целей тестирования использование интерфейса могло бы уменьшить количество головной боли, которую вы бы понесли, если бы у вас были определенные классы, которые вам приходилось бы постоянно воссоздавать, коллекции в целом не так плохи, но наличие контракта интерфейса вы можете легко издеваться, это очень приятно.
Добавлено для редактирования:
Это более несущественно, потому что базовый тип данных - это то, что будет реализовывать метод
См. Ответ Джона Скита для объяснения реализации Count ()
, для массива он должен иметь доступ к известной длине, я бы не беспокоился ни о каких воспринимаемые накладные расходы метода. Count ()
.
T [] (один размер, с нуля) также реализует ICollection
и IList
с IEnumerable
.
Поэтому, если вы хотите меньшего связывания в своем приложении, IEnumerable
предпочтительнее. Если вам не нужен индексированный доступ внутри foreach .
По вашему мнению, если все представление, о котором заботится или должно заботиться, имеет перечислимое значение, это все, что оно должно требовать в своих интерфейсах.
Что это логически (концептуально) извне?
Если это массив, то вернуть массив. Если единственное, что нужно сделать - перечислить, верните IEnumerable. В противном случае IList или ICollection могут быть подходящим вариантом.
Если вы хотите предложить множество функций, но не позволяете их изменять, возможно, используйте List внутри и верните ReadonlyList, возвращенный из этого метода .AsReadOnly ().
Учитывая, что изменить код с массива на IEnumerable позже легко, а вот изменить его другим способом - нет, я бы выбрал IEnumerable, пока вы не узнаете, что вам нужна небольшая часть выгода от возврата массива.