Возвращает IList <T> vs Array в С#?

Недавно я спросил кого-то, почему он предпочел вернуть массив строго типизированный по IList. Я всегда думал, что программирование против интерфейса является наиболее гибким и лучшим способом, когда сталкивается с проектом, имеющим долгую жизнь. Так что это показалось мне странным, когда он ответил:

Обычно мы предпочитаем неизменные типы над изменчивыми. Массивы неизменный. IList не является.

Я не совсем уверен, что понимаю это утверждение. Может кто-нибудь помочь прояснить это?

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

Ответы

Ответ 1

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

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

Например, если у вас была объектная модель поверх репозитория и был метод GetCars(), который возвращал список, а младший программист видел автомобили .Add(Car c)... Не могли бы вы подумать, что он был полностью безумный для мышления cars.Add(новый автомобиль()) может фактически добавить автомобиль в репозиторий? Массивы по своей сути более явны.

Я думаю, что использование списков более подходит для свойств, таких как Page.Controls.Add

Я предпочитаю возвращать массивы чаще, чем List, по нескольким причинам.

  • Привычка

    . Коллекции в 1.0/1.1 SUCKED

  • Я предпочитаю, чтобы мои методы возвращали самый простой и легкий объект, который они могут. Если мне нужно создать массив Array, это тривиально.

  • Они могут использоваться в .net 1.1, и это уменьшает поверхность рефакторинга, если мне когда-либо понадобится поддержка старых версий среды выполнения. Я могу повторно использовать хотя бы часть своего кода или применять идентичную объектную модель.

Ответ 2

Тот, кто "он", на 100% ошибочен по этой теме. Массивы очень изменчивы. На самом деле это одна из причин не возвращать массив. Нельзя предотвратить, чтобы вызывающий пользователь менял элементы массива на все, что угодно.

Единственный способ, с помощью которого Arrray неизменен, - это длина. После выделения массива его длина не может быть изменена. Даже API, такие как Array.Resize, фактически не изменяют размер массива, они просто выделяют новый, копируют содержимое и возвращают новый массив (по ссылке в этом случае).

Я согласен, однако, что существует много случаев, когда лучше возвращать неизменяемые данные. Основной из них заключается в том, что он позволяет вам возвращать ссылку на внутреннюю коллекцию класса без полной копии и в то же время препятствовать тому, чтобы вызывающий пользователь вошел в ваше внутреннее состояние. Большинство изменчивых коллекций не могут предоставлять такие гарантии.

Ответ 3

Я всегда предпочитаю ReadOnlyCollection. Все преимущества списка, но только для чтения.

Ответ 4

Один момент, который он мог иметь в виду, заключается в том, что IList включает методы Insert, Remove и Add, поэтому сама коллекция может быть изменена. T [], с другой стороны, не может добавлять к нему элементы.

Я должен добавить, что FxCop рекомендует возвращать ReadOnlyCollection. Индексатор доступен только для чтения, поэтому вы не можете изменять элементы, а Add и другие подобные методы выбрасывают NotSupportedException.

Ответ 5

В принципе он прав, но он не знает, как правильно практиковать...

Обычно мы предпочитаем неизменные типы над изменчивыми.

Это правильно. Неизменяемые типы лучше работать с

Массивы неизменяемы. IList не является.

Это неверно. Ни один из них не является неизменным.

Если вы хотите вернуть неизменяемую коллекцию, верните IEnumerable<T> или ReadOnlyCollection<T> (используя метод List<T>.AsReadOnly). Тем не менее они не защищают объекты, если они сами не являются неизменными. Несмотря на то, что вы можете читать только из коллекций, вы все равно можете изменять данные в каждом объекте, если они разрешают его.

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

Ответ 6

Я тоже этого не понимаю. Массивы очень изменчивы, за исключением их размера. Отдельные элементы могут быть изменены. Возможно, он имел в виду, что массивы - это типы значений, а списки - ссылочные типы. Я не знаю.

В любом случае, вероятно, вы должны взглянуть на мнение Эрика Липперта по этому вопросу. Могли бы также предоставить вам некоторые боеприпасы для обсуждения.

Ответ 7

Возможно, это кто-то не знает, о чем он говорит?

Ответ 8

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

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

Отдельные проблемы: - вернуть список строго типизированных данных или нет. IList или IList. Использование строго типизированных данных всегда предпочтительнее. - изменчивый или неизменный. ICollection, IList или IEnumerator Вернитесь с тем, что вы хотите разрешить данным. Для списка только для чтения возвратите только IEnumerator. Если вызывающему абоненту разрешено изменять коллекцию, используйте ICollection или IList.

Ответ 9

В основном он говорит: "Мы предпочитаем структуры, которые нельзя легко изменить во время выполнения, потому что мы считаем, что они менее уязвимы для ошибок". Правильно ли в этом случае другой вопрос.

Ответ 10

Возможно, он имел в виду размер массива как "неизменяемый"? В принципе, вы объявляете размер один раз, и вы застряли с ним. Со списками вы всегда можете использовать "Добавить".

Я полагаю, что если вы уверены в размере списка, возможно, массив немного быстрее?

Ответ 11

Ну. IList изменен в том смысле, что вы можете добавлять и удалять элементы, а не просто изменять элементы, которые уже есть. Массив позволяет вам взаимодействовать с отдельными элементами, но конкретный индекс никогда не станет полностью недействительным. Существует несколько причин, чтобы предпочесть неизменность - например, площадь поверхности для случайного повреждения данных намного меньше.