182 votes

Existe-t-il un moyen plus élégant d’ajouter un élément à un dictionnaire <> en toute sécurité?

Je dois ajouter des paires clé / objet à un dictionnaire, mais je dois bien sûr d'abord vérifier si la clé existe déjà, sinon l'erreur "La clé existe déjà dans le dictionnaire ". Le code ci-dessous résout ce problème, mais est maladroit.

Quelle est la manière la plus élégante de faire cela sans créer une méthode d’aide de chaîne comme celle-ci?

 using System;
using System.Collections.Generic;

namespace TestDictStringObject
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, object> currentViews = new Dictionary<string, object>();

            StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view1");
            StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view2");
            StringHelpers.SafeDictionaryAdd(currentViews, "Employees", "view1");
            StringHelpers.SafeDictionaryAdd(currentViews, "Reports", "view1");

            foreach (KeyValuePair<string, object> pair in currentViews)
            {
                Console.WriteLine("{0} {1}", pair.Key, pair.Value);
            }
            Console.ReadLine();
        }
    }

    public static class StringHelpers
    {
        public static void SafeDictionaryAdd(Dictionary<string, object> dict, string key, object view)
        {
            if (!dict.ContainsKey(key))
            {
                dict.Add(key, view);
            }
            else
            {
                dict[key] = view;
            }
        }
    }
}
 

309voto

Jon Skeet Points 692016

Utilisez simplement l'indexeur - il va remplacer si elle est déjà là, mais il ne veut pas avoir à être là en premier:

Dictionary<string, object> currentViews = new Dictionary<string, object>();
currentViews["Customers"] = "view1";
currentViews["Customers"] = "view2";
currentViews["Employees"] = "view1";
currentViews["Reports"] = "view1";

Utiliser Add si l'existence de la clé indique un bug (si vous voulez jeter) et l'indexeur autrement. (C'est un peu comme la différence entre la coulée et à l'aide de as pour la référence de conversions.)

Si vous êtes à l'aide de C# 3 et vous avez un ensemble distinct de touches, vous pouvez rendre le tout encore plus net:

var currentViews = new Dictionary<string, object>()
{
    { "Customers", "view2" },
    { "Employees", "view1" },
    { "Reports", "view1" },
};

Qui ne fonctionne pas dans votre cas, si, comme la collection des initialiseurs de toujours utiliser Add qui vont se jeter sur le deuxième Customers entrée.

63voto

Mehrdad Afshari Points 204872

Quel est le problème avec...

 dict[key] = view;
 

Cela ajoutera automatiquement la clé si elle n'existe pas.

28voto

Steve Gilham Points 7829

simplement

 dict[key] = view;
 

De la documentation MSDN de Dictionary.Item

La valeur associée à la clé spécifiée. Si la clé spécifiée n'est pas trouvée, une opération get lève une exception KeyNotFoundException et une opération set crée un nouvel élément avec la clé spécifiée .

Mon emphase

13voto

Daniel Earwicker Points 63298

Bien que l'utilisation de l'indexeur est clairement le droit de réponse à votre problème spécifique, l'autre, plus générale, de répondre à la problématique de l'ajout de fonctionnalités supplémentaires à un type existant serait de définir une méthode d'extension.

Obviousy ce n'est pas particulièrement utile, par exemple, mais quelque chose à garder à l'esprit pour la prochaine fois que vous trouver un réel besoin:

public static class DictionaryExtensions
{
    public static void SafeAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, 
                                             TKey key, TValue value)
    {
        dict[key] = value;
    }
}

11voto

rohancragg Points 2760

Comme à son habitude, John Skeet arrive à la vitesse d’éclairage avec la bonne réponse, mais il est intéressant de noter que vous auriez aussi pu écrire votre SafeAdd comme méthode d’extension dans IDictionary.

 public static void SafeAdd(this IDictionary<K, T>. dict, K key, T value)...
 

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