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

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

Метод-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;
}

Теперь, мой вопрос: может ли быть какая-то проблема, если я заменил Method-1 на Method-2? Будет ли он нарушаться любым возможным сценарием?

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

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

Ответ 1

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

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


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

Ответ 2

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

Ответ 3

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

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

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

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

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

  • Это в рамках - оно более проверено, и вы не тот, кто должен поддерживать код
  • Он масштабируемый: если вы переключитесь на многопоточность, ваш код уже подготовлен для него

Ответ 4

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

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

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

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