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 .

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.


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.


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

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.