С# string [] vs IEnumerable <string>

Что мне делать, если я знаю количество элементов перед запуском?

Resharper предлагает мне IEnumerable<string> вместо string[]?

Ответы

Ответ 1

Если вы пытаетесь предоставить этот метод в качестве интерфейса для других методов, я бы предпочел, чтобы выход вашего метода был более общим, следовательно, он будет использоваться для IEnumerable<string>.

Внутри метода, если вы пытаетесь создать экземпляр, и это не передается другим методам, я бы пошел на string[]. , если мне не требуется отсроченное выполнение. Хотя, не имеет значения, какой из них вы используете в этом случае.

Ответ 2

ReSharper предлагает IEnumerable<string>, если вы используете только методы, определенные для IEnumerable. Он делает это с идеей, что, поскольку вам явно не нужно значение, которое нужно ввести в качестве массива, вы можете скрыть точный тип от потребителей (т.е. Код, который использует) значение, потому что вы можете захотеть изменить тип в будущем.

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

Из вышесказанного вы также можете сделать вывод о том, что все предложение/вопрос бессмысленно, если значение, о котором мы говорим, передается через границы метода (я не помню, если R # также предлагает его для локальной переменной).

Ответ 3

Если ReSharper предлагает использовать IEnumerable<string>, это означает, что вы используете только функции этого интерфейса и не имеете конкретных функций массива. Пойдите с предложением ReSharper и измените его.

Ответ 4

Фактический тип должен быть строкой [], но в зависимости от пользователя, который вы, возможно, захотите открыть его как что-то еще. например IEnumerable<string> sequence = new string[5]... В частности, если это что-то вроде статической readonly, тогда вы должны сделать это ReadOnlyCollection, чтобы записи не могли быть изменены.

Ответ 5

Вероятно, это говорит об этом, потому что он ищет более качественную Liskov Substitution на этом этапе вашего кода. Имейте в виду разницу между объявленным типом и типом реализации. IEnumerable<> не является реализацией, это интерфейс. Вы можете объявить переменную как IEnumerable<string> и построить ее с помощью string[], поскольку массив строк реализует IEnumerable<string>.

Что это для вас значит, вы можете передать этот массив строк как более общий, более абстрактный тип. Все, что ожидает или возвращает IEnumerable<string> (независимо от реализации, будь то List<string> или string[] или что-то еще), может затем использовать ваш массив строк, не беспокоясь о конкретной реализации, которую вы передаете. Пока он удовлетворяет интерфейсу, он является полиморфным для правильного типа.

Имейте в виду, что это не всегда путь. Иногда вы, как разработчик, очень заинтересованы в реализации (возможно, для очень тонкой настройки производительности, например) и не хотите переходить к абстракции. Решение зависит от вас. ReSharper просто делает предложение использовать абстракцию, а не реализацию в объявлении variable/method.

Ответ 6

ReSharper, вероятно, помещает его для вас, потому что вы не возвращаете наименее ограниченный тип. Если вы не собираетесь использовать доступ к нему по индексу в будущем, я бы пошел с IEnumerable, чтобы иметь меньше ограничений на метод, который возвращает его.

Ответ 7

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

Ответ 8

со строкой [] вы можете сделать больше, вы можете использовать элементы по индексу с помощью IEnumerable, вам нужно петли, чтобы найти определенный индекс

Ответ 9

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

Основное преимущество IEnumerable над T [] заключается в том, что IEnumerable (для возвращаемых значений) может быть ленивым. Т.е. он только вычисляет следующий элемент, когда это необходимо.

Рассмотрим разницу между Directory.GetFiles и Directory.EnumerateFiles. GetFiles возвращает массив, EnumerateFiles возвращает IEnumerable. Это означает, что для каталога с двумя миллионами файлов массив будет содержать два миллиона строк. EnumerateFiles только инициализирует строки по мере необходимости, сохраняя память и улучшая время отклика.

Однако, это не все выгоды.

foreach значительно менее эффективен для не-массивов (вы можете это увидеть, разобрав ILCode).

Массив promises больше, т.е. его длина не изменится.

Ленивая оценка не всегда лучше, рассмотрите класс Directory. Реализация GetFiles откроет дескриптор файла поиска, повторит все файлы, закроет дескриптор файла find и вернет результаты. EnumerateFiles ничего не будет делать до тех пор, пока не будет запрошен первый файл поиска, тогда дескриптор файла поиска будет открыт и файлы будут итерации, найти дескриптор файла будет закрыт, когда перечислитель будет удален. Это означает, что время жизни файла поиска find управляется вызывающим, а не вызываемым. Можно рассматривать как меньшую инкапсуляцию и может давать потенциальные ошибки времени выполнения с заблокированными файловыми дескрипторами.

По моему скромному мнению, я считаю, что R # слишком завышен в предположении IEnumerable над массивами, особенно для возвращаемых значений (входные параметры имеют меньше потенциальных недостатков). То, что я обычно делаю, когда вижу функцию, возвращающую IEnumerable, является .ToArray, чтобы избежать потенциальных проблем с оценкой Lazy, но если коллекция уже является массивом, это неэффективно.

Мне нравится принцип; обещания много, требуют мало. Т.е. не требуется, чтобы входные параметры были массивами (используйте IEnumerable), но возвратите Array поверх IEnumerable, поскольку массив является большим обещанием.