Наследование из списка <T>
Каков самый быстрый способ реализовать новый класс, который наследует от List<T>
?
class Animal {}
class Animals : List<Animal> {} // (1)
Одна из проблем, с которой я столкнулся: просто делая (1), я обнаружил, что я не получаю преимущества наследования каких-либо конструкторов из List<T>
.
В конце концов, я бы хотел, чтобы Animals
вел себя так же, как List<T>
(например, может быть создан, совместим с Linq). Но, кроме того, я также хотел бы иметь возможность добавлять собственные методы.
Ответы
Ответ 1
Если вы хотите создать общедоступную коллекцию животных, вы не должны наследовать от List<T>
и вместо этого наследовать от Collection<T>
и использовать Collection
postfix в имени класса. Пример: AnimalCollection: Collection<Animal>
.
Это подтверждается руководящими принципами разработки рамок, а именно:
НЕ используйте ArrayList
, List<T>
, Hashtable
или Dictionary<K,V>
в публичных API. KeyedCollection<K,T>
используйте Collection<T>
, ReadOnlyCollection<T>
, KeyedCollection<K,T>
или CollectionBase. Обратите внимание, что общие коллекции поддерживаются только в Framework версии 2.0 и выше.
Ответ 2
Конструкторы не наследуются вместе с классом. Вы должны переопределить нужные конструкторы.
public class AnimalsCollection : List<Animal>
{
public AnimalsCollection(IEnumerable<Animal> animals) : base(animals) {}
}
Ответ 3
Вывод из List<T>
не рекомендуется. Прежде всего потому, что List никогда не предназначался для расширения, а для производительности.
Если вы хотите создать свою собственную конкретную коллекцию, вы должны наследовать от Collection<T>
. В вашем случае это будет:
class Animals : Collection<Animal> {}
Ответ 4
Имейте в виду, что наследование от List не так полно, как вам может понадобиться, многие из них не являются виртуальными, поэтому единственный способ охватить базовую реализацию - затенять его синтаксисом new
(как против override
).
Если вам нужно начать подвергать настраиваемое поведение стандартным действиям списка, я бы использовал все интерфейсы списка для типа, который просто использует внутренний список для реального хранилища.
Это сильно зависит от ваших окончательных требований.
Ответ 5
class Animals : List<Animal> {}
выглядит наилучшим образом, потому что вы можете использовать его сразу после определения этого типа.
Итак, мой совет - это название вашего вопроса: Inherit List<T>
; -)
Ответ 6
Нет необходимости наследовать от List
, чтобы использовать синтаксис инициализации коллекции или использовать методы расширения Linq.
Просто реализуйте IEnumerable
, а также метод Add
.