Я должен проверить, присутствует ли конкретный ключ в Словаре прежде, чем получить доступ к нему?

диапазон создает список, поэтому если Вы действительно располагаетесь (1, 10000000), он создает список в памяти с 10 000 000 элементов. xrange является генератором, таким образом, он оценивает лениво.

Это приносит Вам два преимущества:

  1. можно выполнить итерации более длинных списков, не добираясь MemoryError.
  2. , Поскольку это разрешает каждое число лениво при остановке повторения рано Вы не будете напрасно тратить время, создавая целый список.
10
задан Giffyguy 5 August 2009 в 18:20
поделиться

8 ответов

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

Если допустимо отсутствие ключа, используйте вместо него TryGetValue и отреагируйте соответствующим образом.

(Также примените совет Марка по безопасному доступу к общему словарю.)

18
ответ дан 3 December 2019 в 14:44
поделиться

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

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

Однако; если вы уверены, что элемент есть, то с индексатором все будет в порядке:

Foo foo;
lock(syncLock) {
    foo = data[key];
}
// use foo...

В противном случае полезно проверить и добавить ту же блокировку:

Foo foo;
lock(syncLock) {
    if(!data.TryGetValue(key, out foo)) {
        foo = new Foo(key);
        data.Add(key, foo);
    }
}
// use foo...

Здесь мы добавляем элемент только в том случае, если его там не было. .. но внутри того же замка .

10
ответ дан 3 December 2019 в 14:44
поделиться

Всегда проверяйте. Никогда не говори никогда. Я предполагаю, что ваше приложение не настолько критично для производительности, что вам придется экономить время проверки.

СОВЕТ: Если вы решите не проверять, по крайней мере, используйте Debug.Assert (dict.ContainsKey (key)); Он будет скомпилирован только в режиме отладки, ваша сборка выпуска не будет его содержать. Таким образом, у вас будет хотя бы проверка при отладке.

Тем не менее: если возможно, просто проверьте это: -)

РЕДАКТИРОВАТЬ: Здесь были некоторые неправильные представления. Под «всегда проверять» я имел в виду не только использование if где-нибудь. Сюда также входила правильная обработка исключения. Итак, если быть более точным: никогда не принимайте ничего как должное, ожидайте неожиданного. Проверьте с помощью ContainsKey или обработайте возможное исключение, но сделайте ЧТО-ТО, если элемент не содержится.

2
ответ дан 3 December 2019 в 14:44
поделиться

Лично я бы проверил, есть ли ключ, независимо от того, УВЕРЕНЫ вы в нем или нет, некоторые могут сказать, что эта проверка излишняя, и этот словарь выдаст исключение, которое вы можете поймать, но имхо вам не следует полагаться на это исключение, вы должны проверить себя, а затем либо выбросить собственное исключение, которое означает что-то, либо объект результата с флагом успеха и причиной внутри ... механизм сбоя действительно зависит от реализации.

1
ответ дан 3 December 2019 в 14:44
поделиться

TryGetValue - это тот же код, что и индексирование по ключу, за исключением того, что первый возвращает значение по умолчанию (для параметра out ), когда последний вызывает исключение. Используйте TryGetValue , и вы получите последовательные проверки без потери производительности.

Изменить: Как сказал Джон, если вы знаете, что у него всегда будет ключ, вы можете проиндексировать его и позволить соответствующее исключение. Однако, если вы можете предоставить более точную контекстную информацию, добавив к ней подробное сообщение, это будет предпочтительнее.

0
ответ дан 3 December 2019 в 14:44
поделиться

С точки зрения производительности по этому поводу есть два варианта.

1) По возможности избегайте исключений, поскольку исключения стоят дорого, т. Е. Проверьте, прежде чем пытаться получить конкретный ключ из словарь, существует он или нет. На мой взгляд, лучший подход, если есть большая вероятность, его может и не существовать. Это предотвратит довольно распространенные исключения.

2) Если вы уверены, что предмет будет существовать там 99% времени, то не проверяйте его наличие перед тем, как получить к нему доступ. В 1% случаев, когда он не существует, будет сгенерировано исключение, но вы сэкономите время в остальных 99% случаев, не проверяя.

Я говорю, оптимизируйте для большинства, если есть четкий. Если есть какая-то реальная степень неуверенности в существовании объекта, проверьте его перед извлечением.

0
ответ дан 3 December 2019 в 14:44
поделиться

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

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

0
ответ дан 3 December 2019 в 14:44
поделиться

Я думаю, что у Марка и Джона это (как обычно) довольно хорошо посеяно. Поскольку вы также упоминаете производительность в своем вопросе, возможно, стоит подумать о том, как вы блокируете словарь.

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

0
ответ дан 3 December 2019 в 14:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: