Способ добавления нового или обновления существующего элемента в словаре

235

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

Метод 1 (старый код).

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value)
{            
    if (map.ContainsKey(key))
    {
        map[key] = value;
    }
    else
    {
        map.Add(key, value);
    }
}

Хотя я проверил, что map[key]=value делает ту же самую работу. То есть этот метод можно заменить на метод 2 ниже.

Метод-2.

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value)
{
    map[key] = value;
}

Теперь мой вопрос ... Могут ли быть какие-либо проблемы, если я заменю Метод 1 на Метод 2? Это сломается в любом возможном сценарии?

Кроме того, я думаю, что раньше это была разница между HashTable и Dictionary. HashTable позволяет обновить элемент или добавить новый элемент с помощью индексатора, а словарь - нет! Устранена ли эта разница в версиях C #> 3.0?

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

Маниш Басантани
источник

Ответы:

243

Могут ли быть какие-либо проблемы, если я заменю Метод 1 на Метод 2?

Нет, просто используйте map[key] = value. Два варианта эквивалентны.


По Dictionary<>сравнению с Hashtable: Когда вы запускаете Reflector, вы видите, что установщики индексатора обоих классов вызывают this.Insert(key, value, add: false);и addпараметр отвечает за генерирование исключения при вставке дублирующего ключа. Таким образом, поведение одинаково для обоих классов.

ulrichb
источник
44

Нет проблем. Я бы даже удалил их CreateNewOrUpdateExistingиз исходного кода и использовал бы map[key] = valueнепосредственно в вашем коде, потому что это намного удобнее для чтения, потому что разработчики обычно знают, что это map[key] = valueзначит.

Стивен
источник
22

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

Начиная с .net 4.0 существует пространство имен, System.Collections.Concurrentкоторое включает в себя коллекции, которые являются потокобезопасными.

Коллекция System.Collections.Concurrent.ConcurrentDictionary<>делает именно то, что вы хотите. У него есть AddOrUpdate()метод с дополнительным преимуществом, так как он безопасен для потоков.

Если вы находитесь в высокопроизводительном сценарии и не работаете с несколькими потоками, то уже предоставленные ответы map[key] = valueбыстрее.

В большинстве сценариев это преимущество в производительности незначительно. Если это так, я бы посоветовал использовать ConcurrentDictionary, потому что:

  1. Это в рамках - это более проверено, и вы не тот, кто должен поддерживать код
  2. Это масштабируемо: если вы переключаетесь на многопоточность, ваш код уже подготовлен к нему
Луис Филипе
источник
7

Функционально они эквивалентны.

Производительность map[key] = valueбудет быстрее, так как вы делаете только один поиск вместо двух.

По стилю, чем короче, тем лучше :)

Код в большинстве случаев будет нормально работать в многопоточном контексте. Тем не менее, он не является потокобезопасным без дополнительной синхронизации.

ya23
источник