Классы с коллекциями в качестве свойств против классов, наследующих коллекции

Недавно я использовал класс, который наследуется от коллекции, вместо того, чтобы создавать экземпляр коллекции внутри класса, приемлемо ли это или это создает невидимые проблемы в дальнейшем? Примеры ниже для ясности:

public class Cars : List<aCar>

вместо чего-то вроде:

public class Cars
{
 List<aCar> CarList = new List<aCar>();
}

Какие-нибудь мысли?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
0
1 227
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Проблема в том, что ваш класс Cars по-прежнему будет иметь интерфейс, унаследованный от List, что может разрешать операции, которые вам не нужны.

Это зависит от конечной цели вашего класса. Если он будет работать только как ваша собственная реализация коллекции, используйте наследование. Если нет, включите коллекцию как свойство. Второй вариант более универсален:

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

Я неправильно прочитал вопрос ранее.

Я бы предложил использовать композицию вместо наследования. Если вы хотите иметь возможность использовать все забавные вещи LINQ, непременно реализуйте IEnumerable<T> и, возможно, даже IList<T> - но я бы не производил напрямую от List<T>.

Если вы делать хотите получить коллекцию «бесплатно», но при этом сохраните контроль, вы можете использовать CollectionBase. Это по-прежнему связывает вас с точки зрения вашего единственного шанса наследования, но, по крайней мере, вы получаете больше контроля над тем, что происходит в коллекции.

Если вы хотите, чтобы ваш класс Cars действовал так же, как List и имел те же методы, это не так уж плохо. Вы просто извлекаете из этого результат, и все готово. Затем, если вы хотите добавить какие-либо дополнительные функции, вы можете просто объявить эти методы, и все готово. Однако теперь вы привязаны к List, и если List изменится каким-либо нежелательным образом, вы облажались.

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

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

Однако я бы подумал об использовании Collection <T> вместо List <T>, если вам действительно не нужна функциональность в List <T>.

Действительно ли нужен класс «Машины»? Есть ли какие-то дополнительные функции, чем "Список"? Если нет, вам следует использовать «Список» (или лучше «IList»).

Если у класса «Cars» есть какие-либо дополнительные функции, есть два основных сценария:

  • Этот класс является «последним» классом, большой возможности нет, кому-то нужно его расширить. Тогда эта конструкция в порядке.
  • Этот класс, вероятно, будет использоваться как базовый класс. Тогда рекомендую использовать такую ​​конструкцию:

.

public class CarList<T> : List<T> where T : Car {
    // some added functionality
}

Если вы хотите в будущем быть более гибким, вам следует использовать композицию:

public class CarList<T> : IList<T> where T : Car {
    private IList<T> innerList;
    public CarList() { this.innerList = new List<T>(); }

    // implementation of IList<T>

    // some added functionality
}

Другие вопросы по теме