Зачем возвращать интерфейс коллекции, а не конкретный тип?

Я заметил в коде других людей, что методы, возвращающие общие коллекции, почти всегда возвращают интерфейс (например, IEnumerable<T> или IList<T>), а не конкретную реализацию.

У меня есть два связанных вопроса. Во-первых, почему (если вообще) считается лучшим вернуть интерфейс? Во-вторых, существует ли интерфейс коллекции, который включает метод Sort (как это делает List<T>)?

Ответы

Ответ 1

Из С# - Список или IList

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

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

Ответ 2

Для первого вопроса: если вы вернете интерфейс, вы сохраните большую гибкость. Вы можете позже изменить реализацию, чтобы вернуть другой конкретный тип. С другой стороны, это, очевидно, дает абоненту меньше информации, поэтому они не могут выполнять определенные операции. (например, если вы вернете List<T>, вызывающий может использовать ConvertAll и т.д., который они не могут, если вы только объявляете, что возвращаете IList<T>.) В некоторых ситуациях стоит указать конкретный тип; Обычно я предпочитаю, по крайней мере, начинать с интерфейсов, и переходить только к конкретному типу в качестве возвращаемого типа, если обнаруживаю, что часто хочу использовать дополнительные доступные методы.

Во-вторых, никакие стандартные интерфейсы сбора данных не имеют метода Sort. С другой стороны, вы можете написать метод расширения для сортировки любых IList<T>. Лично я обычно предпочитаю методы LINQ OrderBy, OrderByDescending, ThenBy и ThenByDescending... хотя они возвращают новую последовательность, а не сортировку на месте.

Ответ 3

Мы используем интерфейсы, чтобы предоставить нам большую гибкость в нашей реализации. Поэтому, если у вашего метода есть возвращаемый тип IEnumerable, вы можете изменить объект, который он возвращает из списка в массив, не изменяя объекты, зависящие от метода.

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

Ответ 4

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

Что касается другой части вашего вопроса, вы всегда можете использовать IList, а затем использовать LINQ для сортировки:

list.OrderBy(a=>a.Id);