Уровень доступа к данным: разоблачающий список <>: плохая идея?

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

Я собираюсь реализовать Data in a List<>, но я помню, что читал кое-что о том, как не раскрывать тип List для потребителей, если в этом нет необходимости.

public List<User> GetAllUsers() // non C# users: that means List of User :)

Знаете почему (гугл не помог)? Что вы обычно выставляете для такого рода вещей? IList? IEnumerable?

3 ответа

Решение

Обычно лучше всего использовать наименее мощный интерфейс, с которым пользователь все еще может работать. Если пользователю просто нужны перечисляемые данные, верните IEnumerable<User>, Если этого недостаточно, потому что пользователь должен иметь возможность изменять список (внимание! Это не всегда так), вернуть IList<User>,

/РЕДАКТИРОВАТЬ:

Джоэл задает действительный вопрос в своем комментарии: почему действительно предоставляется наименее мощный интерфейс вместо предоставления пользователю максимальной мощности? (Перефразировать)

Идея заключается в том, что метод, возвращающий данные, может не ожидать, что пользователь изменит его содержимое: другой метод класса может все еще ожидать, что список будет непустым после возврата ссылки на него. Представьте, что пользователь удаляет все данные из списка. Другой метод теперь должен сделать дополнительную проверку, что ele, возможно, был ненужен.

Что еще более важно, это раскрывает части внутренней реализации через тип возврата. Если мне нужно изменить реализацию в будущем, чтобы он больше не использовал IList В контейнере возникла проблема: мне нужно либо изменить контракт метода, введя изменение, нарушающее сборку. Или мне нужно скопировать данные в контейнер списка.

В качестве примера представьте, что эффективная реализация использует словарь и просто возвращает Values коллекция, которая не реализует IList,

Определенно что-то. Использование интерфейса уменьшит связность и упростит изменение деталей реализации уровня данных в будущем. Какой интерфейс зависит от обстоятельств. IList хорош, но иногда вам может понадобиться функциональность ICollection или вы хотите указать значения, доступные только для чтения.

Вы должны тщательно подумать, прежде чем возвращать IEnumerable. Если базовый код использует "yield" для генерации IEnumerable или использует LINQ, вы в конечном итоге будете держать открытыми любые используемые ресурсы.

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

С другой стороны, возврат IList подразумевает, что вызывающий абонент может изменить возвращенный список.

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