Это общий вопрос (но я использую C #), каков наилучший способ (лучшая практика), возвращаете ли вы нулевую или пустую коллекцию для метода, у которого коллекция является типом возвращаемого значения?
c#
collections
Ома
источник
источник
Ответы:
Пустая коллекция. Всегда.
Это отстой:
Рекомендуется НИКОГДА не возвращаться
null
при возврате коллекции или перечисления. ВСЕГДА возвращайте пустой перечисляемый / коллекцию. Это предотвращает вышеупомянутую ерунду и предотвращает появление вашего автомобиля среди коллег и пользователей ваших классов.Говоря о свойствах, всегда устанавливайте свою собственность один раз и забудьте о ней
В .NET 4.6.1 вы можете сжать это довольно много:
Говоря о методах, которые возвращают перечислимые значения, вы можете легко вернуть пустое перечисляемое вместо
null
...Использование
Enumerable.Empty<T>()
может рассматриваться как более эффективное, чем возвращение, например, новой пустой коллекции или массива.источник
IEnumerable
илиICollection
не имеет значения , что много. В любом случае, если вы выберете что-то типа,ICollection
они также вернутсяnull
... Я хотел бы, чтобы они вернули пустую коллекцию, но я столкнулся с ними, возвращаяnull
, так что я решил упомянуть об этом здесь. Я бы сказал, что по умолчанию для коллекции перечислимых пусто, а не пусто. Я не знал, что это был такой чувствительный предмет.Из Руководства по разработке структуры, 2-е издание (стр. 256):
Вот еще одна интересная статья о преимуществах отсутствия возврата нулей (я пытался найти что-то в блоге Брэда Абрама, и он связался со статьей).
Отредактируйте - поскольку Эрик Липперт теперь прокомментировал оригинальный вопрос, я также хотел бы дать ссылку на его превосходную статью .
источник
Зависит от вашего контракта и вашего конкретного случая . Обычно лучше возвращать пустые коллекции , но иногда ( редко ):
null
может означать что-то более конкретное;null
.Некоторые конкретные примеры:
null
будет означать, что элемент отсутствует, в то время как пустая коллекция приведет к избыточности (и, возможно, неправильно)<collection />
источник
Есть еще один момент, который еще не был упомянут. Рассмотрим следующий код:
Язык C # вернет пустой перечислитель при вызове этого метода. Поэтому, чтобы соответствовать структуре языка (и, следовательно, ожиданиям программиста), должна быть возвращена пустая коллекция.
источник
Пусто намного удобнее для потребителей.
Существует понятный способ составления пустого перечислимого:
источник
Мне кажется, что вы должны вернуть значение, семантически правильное в контексте, что бы это ни было. Правило, которое гласит «всегда возвращать пустую коллекцию», кажется мне немного упрощенным.
Предположим, например, что в системе для больницы у нас есть функция, которая должна возвращать список всех предыдущих госпитализаций за последние 5 лет. Если клиент не был в больнице, имеет смысл вернуть пустой список. Но что, если клиент оставил эту часть формы доступа пустой? Нам нужно другое значение, чтобы отличать «пустой список» от «нет ответа» или «не знаю». Мы можем выдать исключение, но это не обязательно условие ошибки, и оно не обязательно выводит нас из нормального потока программы.
Меня часто разочаровывают системы, которые не могут различить ноль и отсутствие ответа. У меня было несколько раз, когда система просила меня ввести какое-то число, я вводил ноль и получал сообщение об ошибке, сообщающее, что я должен ввести значение в это поле. Я только что сделал: я вошел в ноль! Но он не примет ноль, потому что не может отличить его от ответа.
Ответ Сондерсу:
Да, я предполагаю, что есть разница между «Человек не ответил на вопрос» и «Ответ был нулевым». Это было пунктом последнего параграфа моего ответа. Многие программы не могут отличить «не знаю» от пустого или нулевого, что кажется мне потенциально серьезным недостатком. Например, я покупал дом год назад или около того. Я зашел на сайт по недвижимости, и там было много домов по цене $ 0. Звучит довольно хорошо для меня: они раздают эти дома бесплатно! Но я уверен, что печальная реальность состояла в том, что они просто не вошли в цену. В этом случае вы можете сказать: «Ну, очевидно, ноль означает, что они не указали цену - никто не собирается сдавать дом бесплатно». Но на сайте также указаны средние цены продажи и продажи домов в разных городах. Я не могу не задаться вопросом, не содержит ли среднее значение нули, что дает неверно низкое среднее значение для некоторых мест. то есть, что в среднем составляет 100 000 долларов США; $ 120 000; и "не знаю"? Технически ответ «не знаю». То, что мы, вероятно, действительно хотим увидеть, - это 110 000 долларов. Но то, что мы, вероятно, получим, составляет 73 333 доллара, что было бы совершенно неправильно. Кроме того, что, если у нас возникла эта проблема на сайте, где пользователи могут сделать заказ онлайн? (В отличие от недвижимости, но я уверен, что вы видели, что это было сделано для многих других продуктов.) Хотели бы мы, чтобы «цена, не указанная еще», была интерпретирована как «бесплатная»? таким образом, давая неправильно низкое среднее значение для некоторых мест. то есть, что в среднем составляет 100 000 долларов США; $ 120 000; и "не знаю"? Технически ответ «не знаю». То, что мы, вероятно, действительно хотим увидеть, - это 110 000 долларов. Но то, что мы, вероятно, получим, составляет 73 333 доллара, что было бы совершенно неправильно. Кроме того, что, если у нас возникла эта проблема на сайте, где пользователи могут сделать заказ онлайн? (В отличие от недвижимости, но я уверен, что вы видели, что это было сделано для многих других продуктов.) Хотели бы мы, чтобы «цена, не указанная еще», была интерпретирована как «бесплатная»? таким образом, давая неправильно низкое среднее значение для некоторых мест. то есть, что в среднем составляет 100 000 долларов США; $ 120 000; и "не знаю"? Технически ответ «не знаю». То, что мы, вероятно, действительно хотим увидеть, - это 110 000 долларов. Но то, что мы, вероятно, получим, составляет 73 333 доллара, что было бы совершенно неправильно. Кроме того, что, если у нас возникла эта проблема на сайте, где пользователи могут сделать заказ онлайн? (В отличие от недвижимости, но я уверен, что вы видели, что это было сделано для многих других продуктов.) Хотели бы мы, чтобы «цена, не указанная еще», была интерпретирована как «бесплатная»? что было бы совершенно неправильно. Кроме того, что, если у нас возникла эта проблема на сайте, где пользователи могут сделать заказ онлайн? (В отличие от недвижимости, но я уверен, что вы видели, что это было сделано для многих других продуктов.) Хотели бы мы, чтобы «цена, не указанная еще», была интерпретирована как «бесплатная»? что было бы совершенно неправильно. Кроме того, что, если у нас возникла эта проблема на сайте, где пользователи могут сделать заказ онлайн? (В отличие от недвижимости, но я уверен, что вы видели, что это было сделано для многих других продуктов.) Хотели бы мы, чтобы «цена, не указанная еще», была интерпретирована как «бесплатная»?
RE, имеющий две отдельные функции, "есть ли?" и "если так, что это?" Да, вы, конечно, можете это сделать, но зачем вам это? Теперь вызывающая программа должна сделать два вызова вместо одного. Что произойдет, если программист не сможет назвать «любой»? и идет прямо к "что это?" ? Будет ли программа возвращать ошибочный ноль? Бросить исключение? Вернуть неопределенное значение? Это создает больше кода, больше работы и больше потенциальных ошибок.
Единственное преимущество, которое я вижу, заключается в том, что оно позволяет вам соблюдать произвольное правило. Есть ли какое-то преимущество в этом правиле, которое стоит того, чтобы соблюдать его? Если нет, зачем?
Ответ на Jammycakes:
Посмотрите, как будет выглядеть реальный код. Я знаю, что вопрос сказал C #, но извините, если я пишу Java. Мой C # не очень острый и принцип тот же.
С нулевым возвратом:
С отдельной функцией:
На самом деле это код на строку или два меньше с нулевым возвратом, так что это не больше нагрузки для вызывающего, а меньше.
Я не вижу, как это создает сухую проблему. Мы не должны выполнять вызов дважды. Если бы мы всегда хотели делать то же самое, когда список не существует, возможно, мы могли бы отодвинуть обработку до функции get-list вместо того, чтобы вызывающая сторона делала это, и поэтому помещение кода в вызывающую функцию было бы СУХИМЫМ нарушением. Но мы почти наверняка не хотим всегда делать одно и то же. В функциях, где у нас должен быть список для обработки, пропущенный список является ошибкой, которая вполне может остановить обработку. Но на экране редактирования мы, конечно, не хотим останавливать обработку, если они еще не вводили данные: мы хотим, чтобы они вводили данные. Таким образом, обработка «без списка» должна выполняться на уровне вызывающей стороны, так или иначе. И то, делаем ли мы это с нулевым возвратом или отдельной функцией, не имеет значения для большего принципа.
Конечно, если вызывающая сторона не проверяет наличие нулевого значения, программа может завершиться с ошибкой нулевого указателя. Но если есть отдельная функция «есть», и вызывающая сторона не вызывает эту функцию, а слепо вызывает функцию «получить список», то что происходит? Если оно выдает исключение или иным образом завершается неудачей, ну, это почти то же самое, что и то, что произойдет, если он вернул значение null и не проверил его Если он возвращает пустой список, это просто неправильно. Вы не можете различить «у меня есть список с нулевыми элементами» и «у меня нет списка». Это все равно, что возвращать ноль для цены, когда пользователь не вводил никакой цены: это просто неправильно.
Я не вижу, как помогает добавление дополнительного атрибута в коллекцию. Звонящий еще должен проверить это. Как это лучше, чем проверка на ноль? Опять же, самое худшее, что может случиться, это то, что программист забудет проверить это и дать неверные результаты.
Функция, которая возвращает ноль, не является сюрпризом, если программист знаком с понятием ноль, означающим «не иметь значения», о котором, я думаю, должен был услышать любой компетентный программист, считает ли он, что это хорошая идея или нет. Я думаю, что наличие отдельной функции - это скорее «неожиданная» проблема. Если программист не знаком с API, когда он запускает тест без данных, он быстро обнаружит, что иногда он возвращает ноль. Но как бы он обнаружил существование другой функции, если ему не пришло в голову, что такая функция может существовать, и он проверит документацию, и документация будет полной и понятной? Я бы предпочел иметь одну функцию, которая всегда дает мне значимый ответ, а не две функции, которые я должен знать и не забывать вызывать обе.
источник
Если пустая коллекция имеет смысл семантически, это то, что я предпочитаю возвращать. Возврат пустой коллекции для
GetMessagesInMyInbox()
сообщений «у вас действительно нет никаких сообщений во входящих», тогда как возвратnull
может быть полезен для сообщения о том, что недостаточно данных, чтобы сказать, как должен выглядеть возвращаемый список.источник
null
значение определенно не выглядит разумным, я думал об этом в более общих чертах. Исключения также хороши для сообщения о том, что что-то пошло не так, но если «недостаточные данные», о которых идет речь, вполне ожидаемы, то исключение может привести к плохому дизайну. Я скорее думаю о сценарии, где это вполне возможно, и нет никакой ошибки для метода, чтобы иногда не иметь возможности рассчитать ответ.Возвращение null может быть более эффективным, так как новый объект не создается. Однако это также часто требует
null
проверки (или обработки исключений).Семантически
null
и пустой список не означают одно и то же. Различия невелики, и один выбор может быть лучше, чем другой в конкретных случаях.Независимо от вашего выбора, документируйте это, чтобы избежать путаницы.
источник
Можно утверждать, что аргументация в пользу Null Object Pattern аналогична аргументации в пользу возврата пустой коллекции.
источник
Зависит от ситуации. Если это особый случай, вернуть null. Если функция просто возвращает пустую коллекцию, то очевидно, что это нормально. Однако возвращать пустую коллекцию в качестве особого случая из-за неверных параметров или по другим причинам НЕ является хорошей идеей, поскольку она маскирует условие особого случая.
На самом деле, в этом случае я обычно предпочитаю генерировать исключение, чтобы убедиться, что оно ДЕЙСТВИТЕЛЬНО не игнорируется :)
Сказать, что это делает код более устойчивым (возвращая пустую коллекцию), поскольку они не должны обрабатывать нулевое условие, плохо, поскольку это просто маскирует проблему, которая должна быть обработана вызывающим кодом.
источник
Я бы сказал, что
null
это не то же самое, что пустая коллекция, и вы должны выбрать, какая из них лучше всего отражает то, что вы возвращаете. В большинстве случаевnull
ничего (кроме SQL). Пустая коллекция - это что-то, хотя и пустое.Если вам нужно выбрать один или другой, я бы сказал, что вы должны стремиться к пустой коллекции, а не к нулю. Но бывают случаи, когда пустая коллекция не совпадает с нулевым значением.
источник
Всегда думайте в пользу ваших клиентов (которые используют ваш API):
Возвращение 'null' очень часто создает проблемы с клиентами, которые неправильно обрабатывают нулевые проверки, что вызывает исключение NullPointerException во время выполнения. Я видел случаи, когда такая пропущенная нулевая проверка приводила к возникновению приоритетной производственной проблемы (клиент использовал foreach (...) для нулевого значения). Во время тестирования проблемы не возникало, потому что данные оперировали немного иначе.
источник
Я хотел бы дать объяснение здесь, с подходящим примером.
Рассмотрим случай здесь ..
Здесь рассмотрим функции, которые я использую ..
Я могу легко использовать
ListCustomerAccount
иFindAll
вместо.,ПРИМЕЧАНИЕ. Так как AccountValue - нет
null
, функция Sum () не вернетсяnull
. Поэтому я могу использовать ее напрямую.источник
У нас было это обсуждение среди команды разработчиков на работе около недели назад, и мы почти единогласно пошли на пустую коллекцию. Один человек хотел вернуть null по той же причине, что и Майк, указанный выше.
источник
Пустая коллекция. Если вы используете C #, предполагается, что увеличение системных ресурсов не является обязательным. В то время как менее эффективный, возврат Пустой Коллекции намного более удобен для вовлеченных программистов (по причине, описанной выше).
источник
Возвращать пустую коллекцию лучше в большинстве случаев.
Причиной этого является удобство реализации вызывающей стороны, согласованный контракт и более простая реализация.
Если метод возвращает нулевое значение для указания пустого результата, вызывающая сторона должна реализовать адаптер проверки на нулевое значение в дополнение к перечислению. Этот код затем дублируется в различных вызывающих программах, так почему бы не поместить этот адаптер в метод, чтобы его можно было использовать повторно.
Допустимое использование null для IEnumerable может указывать на отсутствие результата или сбой операции, но в этом случае следует рассмотреть другие методы, такие как создание исключения.
источник
Смотрите здесь для сложной дерьмовой бури
null
в целом. Я не согласен с утверждением, котороеundefined
является другимnull
, но это все еще стоит прочитать. И это объясняет, почему вы должны избегатьnull
вообще, а не только в случае, который вы спросили. Суть в том, чтоnull
на любом языке это особый случай. Вы должны думатьnull
как об исключении.undefined
отличается тем, что код, имеющий дело с неопределенным поведением, в большинстве случаев является просто ошибкой. C и большинство других языков также имеют неопределенное поведение, но большинство из них не имеют идентификатора для этого языка.источник
С точки зрения управления сложностью, основной целью разработки программного обеспечения, мы хотим избежать распространения ненужной цикломатической сложности на клиентов API. Возврат нулевого значения клиенту аналогичен возврату им стоимости цикломатической сложности другой ветви кода.
(Это соответствует бремени модульного тестирования. Вам потребуется написать тест для нулевого возвращаемого случая, в дополнение к пустому возвращаемому случаю коллекции.)
источник