Почему IList <T>не предоставляет все методы, которые List <T>предоставляет? Какой я должен использовать? - PullRequest
6 голосов
/ 04 марта 2011

Меня всегда учили, что программирование с использованием интерфейса лучше, поэтому параметры моих методов я бы установил на IList<T>, а не List<T> ..

Но это означает, что я должен привести к List<T> только для того, чтобы использовать некоторые методы, например, приходит Find.

Почему это? Должен ли я продолжать программировать с интерфейсами, но продолжать приводить или возвращать?

Я немного запутался, почему Find (например) недоступен на IList<T>, от которого List<T> наследуется.

Ответы [ 8 ]

11 голосов
/ 04 марта 2011

Лично я бы использовал IList<T> вместо List<T>, но затем использовал бы LINQ (Select, Where и т. Д.) Вместо методов, специфичных для списка.

Приведение к List<T> устраняет большую часть смысла использования IList<T> в первую очередь - и фактически делает его более опасным, поскольку реализация может быть чем-то другим , чем List<T> во время выполнения .

6 голосов
/ 04 марта 2011

В случае списков вы можете продолжить программирование для интерфейсов и использовать LINQ для фильтрации ваших объектов.Вы даже можете работать с IEnumerable<T>, который еще выше в иерархии объектов.

Но в более общем случае, если потребителю вашего API необходимо вызвать определенный метод, вы, вероятно, не выбрали правильный интерфейс для предоставления.

2 голосов
/ 04 марта 2011

Я немного запутался, почему Find (например) не доступен в IList, от которого наследуется List.

Хотя я не знаком с процессом принятия решения одизайнеры, есть несколько вещей, о которых они, вероятно, думали.

1) Если не помещать эти методы в IList, цель контракта будет понятнее. Согласно MSDN, IList "Представляет коллекциюобъектов, к которым можно получить индивидуальный доступ по индексу. "Добавление Find изменило бы контракт на доступную для поиска индексируемую коллекцию.

2) Каждый метод, добавляемый к интерфейсу, усложняет реализацию интерфейса. Если все эти методы были в IList, было бы гораздо утомительнее внедрить IList.Тем более, что:

3) Большинство реализаций этих методов будут одинаковыми. Find и несколько других в List действительно будут лучше размещены во вспомогательном классе.Например, ReadOnlyCollection, Collection, ObservableCollection и ReadOnlyObservableCollection.Если бы мне пришлось реализовать Find на всех этих (до LINQ), я сделал бы вспомогательный класс, который принимает IEnumerable и предикат и просто циклически перебирал коллекции и имел бы реализации, вызывающие вспомогательный метод.

4) LINQ (Не столько причина, почему этого не произошло, но и не то, почему она не нужна в будущем.) С LINQ и методами расширения все IEnumerable теперь «имеют» Find как расширение.метод (только они назвали его Где).

1 голос
/ 04 марта 2011

Если вы предоставляете свой метод с параметром IList <>, кто-то может передать, например, ReadOnlyCollection <>, ведь - это IList <>, но - это не Список <>. Таким образом, ваш API будет зависать во время выполнения. Если вы предоставляете открытый метод с параметром IList <>, вы не можете предполагать, что это конкретная реализация IList <>. Вы должны использовать его как IList <> и ничего более.

1 голос
/ 04 марта 2011

Если вы обнаружите, что параметр IList<T>, передаваемый между различными классами, последовательно преобразуется в List<T>, это указывает на фундаментальную проблему в вашем проекте.

Из того, что вы описываете, ясно, что вы хотите использовать полиморфизм, но повторное преобразование на List<T> будет означать, что IList<T> не имеет необходимого вам уровня полиморфизма.

С другой стороны медали вы просто можете использовать неверный полиморфный метод (например, Find вместо FirstOrDefault).

В любом случае вам следует пересмотреть свой дизайн и посмотреть, чего именно вы хотите достичь, и сделать выбор List<T> или IList<T> на основе фактических требований , а не соответствие стилю .

1 голос
/ 04 марта 2011

Я думаю, это потому, что IList может быть разных типов коллекций (т. Е. IEnumerable некоторого вида, массив или около того).

Вы можете использовать метод расширения Where из System.Linq. Старайтесь не возвращаться к списку из IList.

0 голосов
/ 04 марта 2011

Нет, в этом случае нет смысла программировать на интерфейсы, потому что ваш список НЕ является IList с дополнительными методами.

0 голосов
/ 04 марта 2011

Если список представляет собой какую-то часть API или службы, которая предоставляется, то, вероятно, лучше иметь в качестве IList разрешение на внутреннюю смену реализации.

Уже есть много дискуссий на эту тему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...