Зачем мне возвращать IList <T> over List <T>?
Возможный дубликат:
С# - Список <T> или IList <T>
Всюду написано, что вы должны возвращать IList<T>
из своих методов, а не List<T>
, но я не могу найти никаких действительно веских причин. Я продолжаю находить код, который делает это, а затем вызывающий код обычно выполняет одну из двух задач:
- Вызовите
new List<T>(returnedIList)
, чтобы он мог использовать все полезные методы в List
- Возвращает к
List<T>
, поэтому он может использовать все полезные методы в List
Первый - неудобный, а второй - бросок (runtime) InvalidCastException
, если реализация в любом случае изменится на что-то еще (что делает его абсолютно глупым).
Если я использую List<T>
и по какой-то причине должен заменить его реализацией IList<T>
, которую я не могу наследовать от List<T>
, тогда я получу ошибки сборки и должен будет изменить некоторый код. Вероятно, это очень маловероятно, и если это произойдет, это не так много работы, чтобы исправить. Разумеется, не стоит терять преимущества List<T>
и/или бросать /new List<T>
(Exists, Find и т.д.), Чтобы вернуть их для этого маловероятного сценария?
Итак, существуют ли другие причины для возврата IList<T>
?
Ответы
Ответ 1
Причина в том, что ваш метод можно использовать со всем, что реализует IList<T>
, а не только List. Это становится еще хуже, однако, с момента появления Linq, я начал делать много вещей return Enumerable<T>
или даже просто IEnumerable
!
Я не уверен, что понимаю трудность. Если что-то возвращает фактический список, и его возврат зависит от этого, или его использование является специфическим для него, тогда оно должно возвращать List<T>
. Если нет, тогда вам не нужно будет передавать его в список.
Ответ 2
Мне кажется, что вы смотрите на код низкого качества.
Возврат IList<T>
, а не List<T>
позволяет вашему коду быть более гибким. Вы можете заменить реализацию любой коллекцией, которая реализует IList<T>
без нарушения кода вызова. Это хорошая вещь... но только тогда, когда функциональность, определенная в IList<T>
, соответствует вашим потребностям.
Вы можете обобщить это, чтобы сказать, что вы всегда должны возвращать наиболее общий тип. В большинстве случаев вы можете уйти с IEnumerable<T>
, но если вам нужно больше функциональности, то IList<T>
работает. Если это не разрезает, верните конкретный тип и сделайте с ним.
В обеих ситуациях, о которых вы говорите, необходимо использовать что-то, не предоставляемое напрямую IList<T>
(а если нет, то оба этих метода ошибочны). В этих случаях либо метод должен возвращать List<T>
для обеспечения необходимой функциональности, либо вызывающий должен использовать другой метод.
Ответ 3
Действительно, вы должны возвращать IEnumerable, если это возможно, иначе IList.
Причина в том, что в будущем вы захотите использовать что-то другое, чем список. Это не редкость для реализации собственного списка, который реализует IList, а затем вам не нужно менять большую часть вашего кода.
Поиск производных типов из IList, и вы видите, что вы получаете много обращений только в рамках .NET Framework.
Ответ 4
Идея состоит в том, чтобы позволить вызывающему пользователю решить, какую коллекцию они будут использовать. Вы видите, что многие люди возвращаются IEnumerable<T>
, когда могут. Как правило, это считается хорошей практикой. Возвращая IList, позвольте вызывающему абоненту использовать любую реализацию IList, которую они предпочитают, когда возвращать List требует, чтобы они вручную копировали данные List в свой выбор данных.
Возвращение IEnumerable идеально.