292 votes

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

Dans certains codes hérités, j'ai vu la méthode d'extension suivante pour faciliter l'ajout d'un nouvel élément clé-valeur 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);
    }
}

Bien que j'aie vérifié que map[key]=value fait exactement le même travail. C'est-à-dire que 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.. Y a-t-il un problème si je remplace la méthode 1 par la méthode 2 ? Est-ce que ça va casser dans n'importe quel 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 un indexeur, alors que Dictionary ne le permet 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 une exception si l'utilisateur envoie à nouveau la même clé-valeur, la méthode doit simplement mettre à jour l'entrée avec la nouvelle valeur, et créer une nouvelle entrée si une nouvelle paire clé-valeur a été envoyée à la méthode.

312voto

ulrichb Points 8512

Y a-t-il 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 lancez Reflector, vous constatez que les setters d'indexation des deux classes appellent this.Insert(key, value, add: false); et le add est responsable de la levée d'une exception, lors de l'insertion d'une clé dupliquée. Le comportement est donc le même pour les deux classes.

60voto

Steven Points 56939

Il n'y a pas de problème. J'enlèverais même le CreateNewOrUpdateExisting de la source et utiliser map[key] = value directement dans votre code, car il s'agit d'un langage idiomatique du C# ; les développeurs C# savent généralement que map[key] = value signifie ajouter ou mettre à jour.

28voto

Luis Filipe Points 3302

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

À partir de .net 4.0, il y a l'espace de nom System.Collections.Concurrent qui comprend des collections qui sont sûres pour les fils.

La collection System.Collections.Concurrent.ConcurrentDictionary<> fait exactement ce que vous voulez. Il a le AddOrUpdate() avec l'avantage supplémentaire d'être à l'abri des fils.

Si vous êtes dans un scénario de haute performance et que vous ne manipulez 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 en termes de performances est insignifiant. Si c'est le cas, je vous conseille d'utiliser le ConcurrentDictionary car :

  1. Il est dans le cadre - Il est plus testé et vous n'êtes pas celui qui doit maintenir le code.
  2. Il est évolutif : si vous passez au multithreading, votre code y est déjà préparé.

10voto

ya23 Points 6491

Fonctionnellement, ils sont équivalents.

Performances map[key] = value serait plus rapide, car vous ne faites qu'une seule recherche au lieu de deux.

Pour le style, plus c'est court, mieux c'est :)

Dans la plupart des cas, le code semble fonctionner correctement dans un contexte multithread. Il est cependant no thread-safe sans synchronisation supplémentaire.

8voto

Shiran1136460 Points 71

Le seul problème pourrait être qu'un jour

carte[clé] = valeur

se transformera en -

map[key]++ ;

et cela provoquera une KeyNotFoundException.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X