Что касается производительности...
- Преобразование из списка в T[] включает в себя копирование всех данных из исходного списка во вновь выделенный массив.
- Преобразование из T[] в список также включает копирование всех данных из исходного списка во вновь выделенный список.
- Преобразование из List или T[] в IEnumerable включает приведение типов, что занимает несколько циклов процессора.
- Преобразование из IEnumerable в List включает в себя повышение приведения, что также требует нескольких циклов процессора.
- Преобразование из IEnumerable в T[] также включает повышение класса.
- Вы не можете привести IEnumerable к T[] или List, если это не было T[] или List соответственно для начала. Вы можете использовать функции ToArray или ToList, но они также приведут к созданию копии.
- Доступ ко всем значениям по порядку от начала до конца в T[] в прямом цикле будет оптимизирован для использования простой арифметики указателей, что делает его самым быстрым из всех.
- Доступ ко всем значениям по порядку от начала до конца в списке включает проверку на каждой итерации, чтобы убедиться, что вы не получаете доступ к значению за пределами массива, а затем фактический доступ к значению массива.
- Доступ ко всем значениям в IEnumerable включает создание объекта перечислителя, вызов функции Next(), которая увеличивает указатель индекса, а затем вызов свойства Current, которое дает вам фактическое значение и вставляет его в переменную, указанную в вашем операторе foreach. . В общем, это не так плохо, как кажется.
- Доступ к произвольному значению в IEnumerable включает в себя запуск с самого начала и вызов Next() столько раз, сколько вам нужно, чтобы добраться до этого значения. Как правило, это так плохо, как кажется.
По поводу идиом...
В общем, IEnumerable полезен для общедоступных свойств, параметров функций и часто для возвращаемых значений — и только если вы знаете, что собираетесь использовать значения последовательно.
Например, если бы у вас была функция PrintValues, если бы она была написана как PrintValues(List‹T> values), она могла бы иметь дело только со значениями List, поэтому пользователю сначала пришлось бы преобразовать, если, например, они использовали в[]. Аналогично, если функция была PrintValues(T[] values). Но если бы это были PrintValues(значения IEnumerable‹T>), он мог бы иметь дело со списками, T[], стеками, хеш-таблицами, словарями, строками, наборами и т. д. — любой коллекцией, которая реализует IEnumerable, что практически коллекция.
Что касается внутреннего употребления...
- Используйте список, только если вы не уверены, сколько элементов должно быть в нем.
- Используйте T[], если вы знаете, сколько элементов должно быть в нем, но вам нужно получить доступ к значениям в произвольном порядке.
- Придерживайтесь IEnumerable, если это то, что вам дали, и вам просто нужно использовать его последовательно. Многие функции возвращают IEnumerables. Если вам нужно получить доступ к значениям из IEnumerable в произвольном порядке, используйте ToArray().
Кроме того, обратите внимание, что приведение типов отличается от использования ToArray() или ToList() — последнее включает в себя копирование значений, что действительно является ударом по производительности и памяти, если у вас много элементов. Первый просто означает, что «Собака — это животное, поэтому, как и любое другое животное, она может есть» (подавленное) или «Это животное оказалось собакой, поэтому оно может лаять» (подавленное). Точно так же все списки и T[] являются IEnumerables, но только некоторые IEnumerables являются списками или T[]s.
person
Rei Miyasaka
schedule
04.08.2010