Спосіб додавання нового або оновлення існуючого елемента в словнику


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<>vs Hashtable.: Коли ви запускаєте Reflector, ви бачите, що індексатори обох класів викликають, this.Insert(key, value, add: false);а addпараметр відповідає за викид винятку під час вставлення дубліката ключа. Тож поведінка однакова для обох класів.


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буде швидшою, оскільки ви робите лише один пошук замість двох.

Стильний, чим коротше, тим краще :)

Код у більшості випадків, здається, спрацює добре у багатопотоковому контексті. Однак це не є безпечним для потоків без додаткової синхронізації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.