Хобрук: Ваш путь к мастерству в программировании

SingleOrDefault() Генерировать исключение Последовательность содержит более одного совпадающего элемента

у меня есть словарь, и есть несколько элементов, которые были сохранены, как

    Dictionary<string, string> dService = new Dictionary<string, string>();
    dService.Add("UPS Express Plus", "001");
    dService.Add("UPS Express Plus", "054");
    dService.Add("UPS Express", "007");
    dService.Add("UPS Express Saver", "065");
    dService.Add("UPS Expedited", "008");
    dService.Add("UPS Express Plus", "001");

таким образом я пытаюсь получить ключ на основе значения

dService.SingleOrDefault(x => x.Value == ("001")).Key

этот код выдает ошибку. Я искал в Google и нашел решение, которое люди говорят не использовать SingleOrDefault(), а использовать FirstOrDefault()

но у меня нет хорошего объяснения, почему и когда SingleOrDefault() выдает ошибку? я должен предположить, что словарь хранит несколько значений, поэтому SingleOrDefault() не будет работать?

ищу объяснение, когда, почему и когда SingleOrDefault() выдает ошибку .... пожалуйста, укажите примерную ситуацию. Спасибо

24.07.2014

  • stackoverflow.com /вопросы/21435634/ 24.07.2014
  • Это не вызывает исключения. 24.07.2014
  • почему и когда выдает ошибку SingleOrDefault(). Согласно документации: [SingleOrDefault] возвращает только элемент последовательности или значение по умолчанию, если последовательность пуста; этот метод выдает исключение, если в последовательности более одного элемента. 24.07.2014
  • этот код выдает ошибку. Какая ошибка? Это не вызывает никаких исключений для меня. Вероятно, исключение где-то еще.. 24.07.2014
  • Вы не предоставили минимальный, полный и проверяемый пример. Бьюсь об заклад, ваш реальный словарь содержит как минимум две пары KeyValuePair со значением "001". 24.07.2014
  • да, ты прав... у меня в словаре два 001. 24.07.2014

Ответы:


1

Во-первых, ваши образцы данных выше не выбрасываются, поскольку они не содержат несколько одинаковых значений, которые равны "001". Это было бы, если бы вы добавили два значения с Value="001".

Если вы перечислите словарь, вы получите IEnumerable<KeyValuePair<TKey, TValue>>. Вы запрашиваете первое и единственное значение в словаре, которое равно "001". Конечно, словарь может содержать несколько одинаковых значений (но только уникальные ключи).

Таким образом, вместо этого вы можете использовать FirstOrDefault, который не выдает несколько результатов. Другой способ — найти все с помощью Where, затем Select ключа:

IEnumerable<string> all001ValKeys = dService
    .Where(kv => kv.Value == "001")
    .Select(kv => kv.Key);

SingleOrdefault (или Single) удобен, если вы хотите обеспечить бизнес-правило, например:

var record = someTable.Single(obj => obj.ID == 123); // ID must be unique

Это делает ваш код более читабельным, а также следует правилу «быстрой ошибки».

24.07.2014
  • Кроме того, Single проверит каждый объект, содержащийся в списке, в то время как First остановится на первом подходящем элементе. 24.07.2014
  • @gretro: он не будет проверять каждый объект, он просто проверит, есть ли еще один. Это разница, поскольку производительность не должна быть критерием, позволяющим избежать Single/SingleOrDefault. Выберите то, что лучше всего соответствует вашим бизнес-правилам. 24.07.2014

  • 2

    FirstOrDefault используется, если вам нужен первый элемент в списке, если в списке нет данных, он вернет вам значение по умолчанию (которое равно нулю), иначе он вернет вам первый элемент списка.

    SingleOrDefault используется, когда вы уверены, что в списке есть только один элемент, если его нет в списке, он вернет значение по умолчанию (которое равно нулю), но если он имеет более одного значения, он выдаст вам exectption.

    Я надеюсь, что это объяснение является полным для вас.

    24.07.2014

    3

    Обратите внимание, что FirstOrDefault в словаре возвращает KeyValuePair, содержащую значения по умолчанию для определенных типов Key и Value. Поскольку вы используете строку в качестве ключа и значения, оба значения будут нулевыми. Таким образом, результат вашего выражения LINQ будет нулевым, и работа с ключом может привести к исключению NullReferenceException позже в вашем коде.

    24.07.2014
  • Ты не прав. Идите и попробуйте сами, он вернет KeyValuePair, содержащую значения по умолчанию для указанных типов. 24.07.2014
  • Ваш пример всегда возвращает результат и никогда не возвращает значения по умолчанию, так как нет предиката. Но new Dictionary<string, string> { { "A", "001" } }.FirstOrDefault(x => x.Value == "002"); возвращает KeyValuePair, который сам НЕ является нулевым, но содержит два нулевых значения. 24.07.2014
  • Теперь я понимаю вашу точку зрения, KeyValuePair<Tk, Tv> - это структура, а не класс. struct является типом значения и всегда имеет значение (по умолчанию). 24.07.2014
  • Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..