В чем преимущество использования List <T>перед IEnumerable <T>? - PullRequest
9 голосов
/ 09 ноября 2009

или наоборот?

Я использую общие списки все время. Но я иногда слышу и о IEnumerables, и я, честно говоря, понятия не имею (на сегодня), для чего они и зачем мне их использовать. Поэтому, рискуя навсегда что-то объявить в сети о своем невежестве, я смиренно отвечаю на этот вопрос.

Ответы [ 8 ]

16 голосов
/ 09 ноября 2009

Ну, List<T> реализует IEnumerable<T> ... в основном IEnumerable<T> - это просто последовательность элементов. Вы можете прочитать это, и это все.

List<T> является изменяемой коллекцией - вы можете добавлять в нее, удалять из нее, сортировать и т. Д. Она сама по себе более гибкая, но IEnumerable<T> позволяет использовать один и тот же код для работы с любой реализацией (массивы связанные списки, списки, итераторы, возвращаемые из методов с использованием yield операторов и т. д.).

6 голосов
/ 23 мая 2010

Джон Скит и другие предложили краткий обзор функциональности List над IEnumerable, поэтому я решил заполнить вторую половину вопроса «Каковы преимущества использования IEnumerable над List?».

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

Во-вторых, IEnumerable является абстракцией для перечисления, тогда как List является одной из реализаций этой абстракции. Следуя указаниям Шаблоны проектирования - элементы многоразового объектно-ориентированного программного обеспечения , программирование абстракций над реализациями помогает повысить устойчивость приложений к изменениям, позволяя позднее изменять реализации, не влияя на потребление кода. Если вам нужно поведение списка, вы должны выставить IList, а не List напрямую.

6 голосов
/ 09 ноября 2009

IEnumerable<T> - более общий интерфейс, поэтому вы можете заменить все, что реализует этот интерфейс, для вашей операции. Если у вас есть этот метод:

public void DoSomething(IEnumerable<T> enumerable) {
}

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

Если указать, что объект является List<T>, метод будет работать только на List<T> объектах или экземплярах, которые наследуются от него.

Преимущество использования List<T> состоит в том, что списки имеют гораздо больше возможностей, чем перечислимые. Когда вам нужны эти функции (вставка, поиск, преобразование и многое другое), List<T> или IList<T> более уместно.

2 голосов
/ 09 ноября 2009

Самыми большими преимуществами List<T> перед IEnumerable<T> являются следующие

  1. Случайный доступ
  2. Количество объектов
  3. Метод ForEach
  4. Изменчивость

Первые 2 также легко сделать на IEnumerable<T>, но вы не можете гарантировать скорость O (1). В случае Count вы даже не можете гарантировать реальный ответ, поскольку IEnumerable<T> может легко представлять бесконечные списки.

1 голос
/ 09 ноября 2009

Список предоставляет дополнительные методы по сравнению с IEnumerable. Вы не можете добавить или удалить с помощью IEnumerable, но вы можете сделать это с помощью List.

IEnumerable следует использовать, когда вы планируете зацикливаться только на данных. Это дает вам преимущество перед IList, потому что вам не нужно загружать все данные сразу, чтобы передать доступ к данным, вы просто должны быть в состоянии получить следующую запись через перечислитель. IEnumerable также является интерфейсом, поэтому вы можете «скрыть» тип реального объекта, содержащего данные List, Array и т. Д.

0 голосов
/ 05 июня 2011

Одно из преимуществ IEnumerable, которое еще не было упомянуто: Contravariance. Процедура, ожидающая IEnumerable (Of Car), будет совершенно счастлива, если ей будет дан IEnumerable (Of HondaCivic), что, в свою очередь, означает, что она будет счастлива с IList (Of HondaCivic). Напротив, рутина, которая ожидает IList (Of Car), не будет удовлетворена IList (HondaCivic). Если бы Microsoft IList был получен из интерфейса IReadableByIndex, доступного только для чтения, то код, который ожидал IReadableByIndex (Of Car), был бы полностью доволен IReadableByIndex (Of HondaCivic), но это вода под мостом.

0 голосов
/ 09 ноября 2009

IEnumerable имеет чистую семантику «только для чтения» и «перечисляемый» или «запрашиваемый». С List, похоже, вы позволяете кому-либо изменять его :).

0 голосов
/ 09 ноября 2009

Если вам нужна только функциональность, представленная и реализованная в IEnumerable<T>, вам следует пойти на это. Альтернатива - IEnumerable<T> where T : IFoo, если вы хотите иметь возможность перебирать объекты, реализующие интерфейс IFoo. Если вам, однако, требуются свойства типа Count и такие, которые выставляет List<T>, вы должны пойти на это. Найдите наименьший общий знаменатель и соглашайтесь с этим, поскольку он делает ваши методы более универсальными и с ними легче работать.

...