Возвращение 'IList' против 'ICollection' vs 'Collection'

Я смущен о том, какой тип коллекции должен возвращать из моих общедоступных методов и свойств API.

Коллекции, которые я имею в виду, это IList, ICollection и Collection.

Является ли возврат одного из этих типов предпочтительным для других или зависит от конкретной ситуации?

Ответ 1

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

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

Ответ 2

ICollection<T> - это интерфейс, который предоставляет семантику коллекции, такую ​​как Add(), Remove() и Count.

Collection<T> - это конкретная реализация интерфейса ICollection<T>.

IList<T> по существу является ICollection<T> со случайным доступом на основе порядка.

В этом случае вы должны решить, нужны ли результаты для семантики списка, например, индексирование на основе заказа (затем используйте IList<T>), или вам просто нужно вернуть неупорядоченный "пакет" результатов (затем используйте ICollection<T>).

Ответ 3

Основное различие между IList<T> и ICollection<T> заключается в том, что IList<T> позволяет вам обращаться к элементам через индекс. IList<T> описывает типы, подобные массиву. Элементы в ICollection<T> могут быть доступны только через перечисление. Оба позволяют вставлять и удалять элементы.

Если вам нужно только перечислить коллекцию, то предпочтительнее использовать IEnumerable<T>. Он имеет два преимущества перед другими:

  • Он запрещает изменения в коллекции (но не ссылается на объекты, если элементы являются ссылками).

  • Он позволяет использовать максимально возможное множество источников, включая перечисления, которые генерируются алгоритмически и вообще не являются коллекциями.

Collection<T> - базовый класс, который в основном полезен разработчикам коллекций. Если вы откроете его в интерфейсах (API), многие полезные коллекции, не вытекающие из него, будут исключены.


Одним из недостатков IList<T> является то, что массивы реализуют его, но не позволяют добавлять или удалять элементы (т.е. вы не можете изменить длину массива). Исключение будет вызываться, если вы вызываете IList<T>.Add(item) в массиве. Ситуация несколько разряжена, поскольку IList<T> имеет логическое свойство IsReadOnly, которое вы можете проверить, прежде чем пытаться это сделать. Но в моих глазах это все еще недостаток дизайна в библиотеке. Поэтому я использую List<T> напрямую, когда требуется добавить или удалить элементы.

Ответ 4

IList<T> - базовый интерфейс для всех общих списков. Поскольку это упорядоченная коллекция, реализация может принять решение о заказе, начиная от упорядоченного порядка и заканчивая порядком размещения. Более того, Ilist имеет свойство Item, которое позволяет методам читать и редактировать записи в списке на основе их индекса. Это позволяет вставлять, удалять значение в/из списка с индексом позиции.

Также, поскольку IList<T> : ICollection<T>, все методы из ICollection<T> также доступны здесь для реализации.

ICollection<T> - базовый интерфейс для всех общих коллекций. Он определяет размер, счетчики и методы синхронизации. Вы можете добавить или удалить элемент в коллекцию, но вы не можете выбрать, в какой позиции это происходит из-за отсутствия свойства индекса.

Collection<T> обеспечивает реализацию для IList<T>, Ilist и IReadOnlyList<T>.

Если вы используете более узкий тип интерфейса, например ICollection<T> вместо IList<T>, вы защищаете свой код от нарушения изменений. Если вы используете более широкий тип интерфейса, например IList<T>, вам больше угрожает нарушение изменений кода.

Цитата из источника,

ICollection, ICollection<T>: вы хотите изменить коллекцию или вы заботитесь о его размере. Ilist, IList<T>: вы хотите изменить коллекцию и заботиться о упорядочении и/или позиционировании элементов в коллекции.

Ответ 5

Возвращение типа интерфейса более общее, поэтому (не имея дополнительной информации о вашем конкретном случае использования), я бы склонялся к этому. Если вы хотите открыть поддержку индексирования, выберите IList<T>, иначе ICollection<T> будет достаточно. Наконец, если вы хотите указать, что возвращаемые типы являются только для чтения, выберите IEnumerable<T>.

И, если вы еще не прочитали его раньше, Брэд Абрамс и Кшиштоф Квалина написал замечательную книгу под названием "Руководства по дизайну рамок: условности, идиомы и шаблоны для многоразовых библиотек .NET" (вы можете загрузить дайджест из здесь).

Ответ 6

Есть некоторые темы, которые исходят из этого вопроса:

  • интерфейсы и классы
  • какой конкретный класс, из нескольких одинаковых классов, коллекции, списка, массива?
  • Коллекции общих классов и подэлементов ( "generics" )

Вы можете выделить, что его Object Oriented A.P.I.

интерфейсы и классы

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

И, закончив плохое проектирование интерфейса, а не хороший дизайн класса, который, кстати, в конечном итоге может быть перенесен на хороший дизайн интерфейса...

В A.P.I вы увидите много интерфейсов, но не спешите с ним, если вам это не нужно.

В конечном итоге вы узнаете, как применять интерфейсы к вашему коду.

, какой конкретный класс, из нескольких одинаковых классов, сбор, список, массив?

Существует несколько классов в С# (dotnet), которые могут быть взаимозаменяемы. Как уже упоминалось, если вам нужно что-то из более определенного класса, например "CanBeSortedClass", тогда сделайте его явным в вашем A.P.I..

Является ли ваш A.P.I. пользователь действительно должен знать, что ваш класс может быть отсортирован или применить какой-то формат к элементам? Затем используйте "CanBeSortedClass" или "ElementsCanBePaintedClass", в противном случае используйте "GenericBrandClass".

В противном случае используйте более общий класс.

Коллекции общих коллекций и подэлементов ( "generics" )

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

Общие Коллекции - это те классы, которые вы можете использовать одну и ту же коллекцию, для нескольких приложений кода, без необходимости создавать новую коллекцию, для каждого нового типа подтипа, например: Collection.

Является ли ваш A.P.I. пользователю нужен очень специфический тип, такой же для всех элементов?

Используйте что-то вроде List<WashingtonApple>.

Является ли ваш A.P.I. пользователю понадобится несколько связанных типов?

Откройте List<Fruit> для вашего A.P.I. и используйте List<Orange> List<Banana>, List<Strawberry> внутри, где Orange, Banana и Strawberry являются потомками из Fruit.

Является ли ваш A.P.I. пользователю понадобится общий набор типов?

Используйте List, где все элементы object (s).

Приветствия.