Наследование из списка <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.