диапазон создает список, поэтому если Вы действительно располагаетесь (1, 10000000), он создает список в памяти с 10 000 000 элементов. xrange является генератором, таким образом, он оценивает лениво.
Это приносит Вам два преимущества:
MemoryError
. Используйте индексатор, если ключ должен присутствовать - если он не присутствует, он выдаст соответствующее исключение, что является правильным поведением, если отсутствие ключа указывает на ошибку.
Если допустимо отсутствие ключа, используйте вместо него TryGetValue
и отреагируйте соответствующим образом.
(Также примените совет Марка по безопасному доступу к общему словарю.)
Если словарь глобальный (статический / общий), вы должны синхронизировать доступ к нему (это важно, иначе вы можете его повредить).
Даже если ваш поток только читает данные, ему необходимо учитывать блокировки других потоков, которые могут его редактировать.
Однако; если вы уверены, что элемент есть, то с индексатором все будет в порядке:
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...
Здесь мы добавляем элемент только в том случае, если его там не было. .. но внутри того же замка .
Всегда проверяйте. Никогда не говори никогда. Я предполагаю, что ваше приложение не настолько критично для производительности, что вам придется экономить время проверки.
СОВЕТ: Если вы решите не проверять, по крайней мере, используйте Debug.Assert (dict.ContainsKey (key)); Он будет скомпилирован только в режиме отладки, ваша сборка выпуска не будет его содержать. Таким образом, у вас будет хотя бы проверка при отладке.
Тем не менее: если возможно, просто проверьте это: -)
РЕДАКТИРОВАТЬ: Здесь были некоторые неправильные представления. Под «всегда проверять» я имел в виду не только использование if где-нибудь. Сюда также входила правильная обработка исключения. Итак, если быть более точным: никогда не принимайте ничего как должное, ожидайте неожиданного. Проверьте с помощью ContainsKey или обработайте возможное исключение, но сделайте ЧТО-ТО, если элемент не содержится.
Лично я бы проверил, есть ли ключ, независимо от того, УВЕРЕНЫ вы в нем или нет, некоторые могут сказать, что эта проверка излишняя, и этот словарь выдаст исключение, которое вы можете поймать, но имхо вам не следует полагаться на это исключение, вы должны проверить себя, а затем либо выбросить собственное исключение, которое означает что-то, либо объект результата с флагом успеха и причиной внутри ... механизм сбоя действительно зависит от реализации.
TryGetValue
- это тот же код, что и индексирование по ключу, за исключением того, что первый возвращает значение по умолчанию (для параметра out
), когда последний вызывает исключение. Используйте TryGetValue
, и вы получите последовательные проверки без потери производительности.
Изменить: Как сказал Джон, если вы знаете, что у него всегда будет ключ, вы можете проиндексировать его и позволить соответствующее исключение. Однако, если вы можете предоставить более точную контекстную информацию, добавив к ней подробное сообщение, это будет предпочтительнее.
С точки зрения производительности по этому поводу есть два варианта.
1) По возможности избегайте исключений, поскольку исключения стоят дорого, т. Е. Проверьте, прежде чем пытаться получить конкретный ключ из словарь, существует он или нет. На мой взгляд, лучший подход, если есть большая вероятность, его может и не существовать. Это предотвратит довольно распространенные исключения.
2) Если вы уверены, что предмет будет существовать там 99% времени, то не проверяйте его наличие перед тем, как получить к нему доступ. В 1% случаев, когда он не существует, будет сгенерировано исключение, но вы сэкономите время в остальных 99% случаев, не проверяя.
Я говорю, оптимизируйте для большинства, если есть четкий. Если есть какая-то реальная степень неуверенности в существовании объекта, проверьте его перед извлечением.
Если вы знаете, что словарь обычно содержит ключ, вам не нужно проверять его перед тем, как получить к нему доступ.
Если что-то не так и словарь не содержит элементы, которые должны, вы можете позволить словарю выдать исключение. Единственная причина для проверки ключа в первую очередь - это если вы хотите самостоятельно решить эту проблемную ситуацию, не получая исключения. Позволить словарю генерировать исключение и перехватить, что, однако, является вполне допустимым способом обработки ситуации.
Я думаю, что у Марка и Джона это (как обычно) довольно хорошо посеяно. Поскольку вы также упоминаете производительность в своем вопросе, возможно, стоит подумать о том, как вы блокируете словарь.
Простая блокировка
сериализует весь доступ для чтения, что может быть нежелательно, если чтение выполняется очень часто, а записи относительно мало . В этом случае лучше использовать ReaderWriterLockSlim
. Обратной стороной является то, что код немного сложнее, а запись немного медленнее.