Должен ли List <T> быть закрытым?

Мне нужно ваше мнение об этом, потому что я прочитал много разных вещей по этому вопросу. Если у вас есть List<T> или какой-либо список в объявлении класса, вы делаете его закрытым, а затем добавляете или удаляете элементы с использованием определенных методов или публикуете его?

Ваши взгляды будут высоко оценены с любыми недостатками/преимуществами каждого варианта.

Чтобы привести пример, скажем, мы имеем class Employer с частными полями name и List<Employees>. Мой вопрос в том, следует ли нам сделать список сотрудников частным или общедоступным и какие преимущества/недостатки будут в обоих случаях.

Ответ 1

для списка явно да, он должен быть закрытым, в зависимости от того, что должны выполнять функции, которые вы подвергаете, такие интерфейсы, как IEnuemerable, ICollection или IList, были бы лучшим выбором или если вы выставили коллекцию. См. ответ SLaks.

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

Далее, если вы используете интерфейс, вы должны использовать узкий интерфейс.

Итак, если код клиента должен только перечислить его. используйте IEnumerable, если код клиента должен индексировать использование ICollection и т.д.

далее, если вы выставляете IEnumerable, вы должны убедиться, что когда-либо вы вернулись, на самом деле читается только с использованием класса коллекции только для чтения или с помощью блока iterator

ИЗМЕНИТЬ после обновления Что касается вашего примера. Спросите себя, имеет ли смысл, что любой, кроме Работодателя, может изменить, кто его сотрудники? для меня это в словах, которые вы уже выбрали. Работодатель использует Работника и должен иметь полный контроль над тем, кто его/ее сотрудники. Поэтому в этом конкретном случае я бы оставил его конфиденциальным и разоблачил Hire (сотрудник IEmployee) и Fire (сотрудник IEmployee) таким образом, что в коде явно указано намерение

Ответ 2

Если вам нужно предоставить коллекцию пользователям вашего класса, вы должны сделать свойство readonly с System.Collections.ObjectModel.Collection<T>.

Затем вы можете наследовать этот класс и переопределить InsertItem, RemoveItem и SetItem для запуска пользовательской логики, когда пользователь манипулирует коллекцией.

Если вы не хотите, чтобы пользователь мог изменять коллекцию, вы должны открыть ReadOnlyCollection<T>.

В вашем конкретном примере вы должны, вероятно, открыть ReadOnlyCollection<Employee> с помощью отдельных методов мутатора в Employer.

Ответ 3

И если вы хотите, чтобы кто-то мог перечислить список, вы можете открыть iEnumerable, функция GetEnumerator которого будет просто вызывать функцию GetEnumerator списка.

Ответ 4

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

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

Ответ 5

В зависимости от требуемой функциональности. Если вы просто хотите, чтобы люди могли манипулировать списком, вы можете открыть его через свойство только для чтения (без установщика). Если вы хотите, чтобы дополнительный код выполнялся, когда пользователи манипулировали списком, вы должны написать свои собственные методы, а не раскрывать список.