Способ добавления нового или обновления существующего элемента в словаре - PullRequest
189 голосов
/ 22 ноября 2010

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

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

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

Ответы [ 4 ]

199 голосов
/ 22 ноября 2010

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

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

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

39 голосов
/ 22 ноября 2010

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

17 голосов
/ 16 ноября 2013

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

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

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

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

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

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

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

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

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

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

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