Méthode pour ajouter un nouvel élément ou mettre à jour un élément existant dans le dictionnaire

235

Dans certains codes hérités, j'ai vu la méthode d'extension suivante pour faciliter l'ajout d'un nouvel élément de valeur-clé ou la mise à jour de la valeur, si la clé existe déjà.

Méthode 1 (code hérité).

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);
    }
}

Cependant, j'ai vérifié que cela map[key]=value fait exactement le même travail. Autrement dit, cette méthode pourrait être remplacée par la méthode-2 ci-dessous.

Méthode-2.

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

Maintenant, ma question est .. Pourrait-il y avoir un problème si je remplace la méthode-1 par la méthode-2? Va-t-il se casser dans un scénario possible?

De plus, je pense que c'était la différence entre HashTable et Dictionary. HashTable permet de mettre à jour un élément, ou d'ajouter un nouvel élément en utilisant l'indexeur alors que Dictionary ne le fait pas !! Cette différence a-t-elle été éliminée dans les versions C #> 3.0?

L'objectif de cette méthode n'est pas de lever trop d'exception si l'utilisateur envoie à nouveau la même valeur-clé, la méthode doit simplement mettre à jour l'entrée avec la nouvelle valeur, et faire une nouvelle entrée si une nouvelle paire clé-valeur a été envoyée à la méthode .

Manish Basantani
la source

Réponses:

243

Pourrait-il y avoir un problème si je remplace la méthode 1 par la méthode 2?

Non, utilisez simplement map[key] = value. Les deux options sont équivalentes.


Concernant Dictionary<>vs Hashtable: Lorsque vous démarrez Reflector, vous voyez que les setters indexeurs des deux classes appellent this.Insert(key, value, add: false);et que le addparamètre est responsable de lever une exception, lors de l'insertion d'une clé en double. Le comportement est donc le même pour les deux classes.

ulrichb
la source
44

Il n'y a aucun problème. Je supprimerais même le CreateNewOrUpdateExistingde la source et l'utiliserais map[key] = valuedirectement dans votre code, car c'est beaucoup plus lisible, car les développeurs savent généralement ce que cela map[key] = valuesignifie.

Steven
la source
22

Ancienne question mais je pense que je devrais ajouter ce qui suit, d'autant plus que .net 4.0 avait déjà été lancé au moment où la question a été écrite.

À partir de .net 4.0, il y a l'espace de noms System.Collections.Concurrentqui inclut les collections qui sont thread-safe.

La collection System.Collections.Concurrent.ConcurrentDictionary<>fait exactement ce que vous voulez. Il a la AddOrUpdate()méthode avec l'avantage supplémentaire d'être thread-safe.

Si vous êtes dans un scénario haute performance et ne gérez pas plusieurs threads, les réponses déjà données de map[key] = value sont plus rapides.

Dans la plupart des scénarios, cet avantage de performance est insignifiant. Si c'est le cas, je vous conseille d'utiliser le ConcurrentDictionary parce que:

  1. C'est dans le cadre - C'est plus testé et ce n'est pas vous qui devez maintenir le code
  2. Il est évolutif: si vous passez au multithreading, votre code est déjà préparé pour cela
Luis Filipe
la source
7

Fonctionnellement, ils sont équivalents.

Les performances map[key] = valueseraient plus rapides, car vous ne faites qu'une seule recherche au lieu de deux.

Côté style, plus c'est court, mieux c'est :)

Dans la plupart des cas, le code semble fonctionner correctement dans un contexte multithread. Cependant, il n'est pas thread-safe sans synchronisation supplémentaire.

ya23
la source