Коллекции и списки

Является ли довольно безопасным предположение, что следующий класс является нечетным представлением "понижения" (из-за отсутствия лучшего слова) поля частного класса?

public class AggregatedClass : ICollection<SingleClass>
{
    List<SingleClass> _singleClassList;

    // ...rest of code
}

Недавно я увидел "рабочий" пример этого, и он бросил меня на бит цикла. В чем смысл вышесказанного? Если List<T> реализует ICollection<T>, то не является ли это вышеперечисленным классом? У вас есть поле частного класса, которое type class является расширением его реализации родительского класса (ICollection<T>).

Можно ли сказать, что приведенный выше пример не является отличным дизайном?

Ответ 1

Это абстрагирует List<T> как деталь реализации, и если это необходимо/необходимо, класс может теперь предоставить дополнительную логику в различных методах списка (Add/Remove и т.д.), отметив, что они не являются виртуальными в List-of- Т).

Если вы имеете в виду, что поле должно быть ICollection - ну, это зависит от класса! Он может использовать дополнительные методы List-of-T, или это может быть просто нерелевантная деталь реализации, которая была удобна для тех, кто написал класс, и не наносит никакого вреда, поскольку он все равно является приватным.

Ответ 2

Я бы сказал, что в этом нет ничего плохого. AggregatedClass предоставляет контракт, который ICollection<SingleClass> и как реализован этот контракт, представляет собой деталь реализации, не предназначенную для каламбура.

Если для примера класс был определен как:

public class AggregatedClass : List<SingleClass>

тогда я должен был бы сказать, что да, есть проблема с дизайном. Рекомендуется не раскрывать List<T> в общедоступном API и вместо этого выставлять Collection<T>, поскольку коллекция предоставляет виртуальные методы, такие как InsertItem и ClearItems, а список не предоставляет никаких виртуальных методов, которые могут позже будет использоваться для переопределения поведения в базовом классе.

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

Ответ 3

Это почти зависит от того, что AggregatedClass будет делать в ближайшем будущем: путем реализации ICollection с использованием частного поля разработчик может освободить AggregatedClass от другого.

Так как С# не допускает множественного наследования, это ценная вещь.

На мой взгляд, если класс является "главным образом" списком, я бы получил его непосредственно. В случае, когда мне нужно наследовать из другого класса, всегда можно реорганизовать класс так, как вы указали в своем вопросе.