web-dev-qa-db-fra.com

Créer un dictionnaire constant en C #

Quel est le moyen le plus efficace de créer un mappage constant (jamais modifié au moment de l'exécution) de strings à ints?

J'ai essayé d'utiliser un const Dictionary , mais cela n'a pas fonctionné.

Je pourrais mettre en œuvre un wrapper immuable avec une sémantique appropriée, mais cela ne semble toujours pas totalement correct.


Pour ceux qui ont demandé, j'implémente IDataErrorInfo dans une classe générée et je cherche un moyen de faire en sorte que le paramètre columnName soit consulté dans mon tableau de descripteurs.

Je ne savais pas (faute de frappe lors des tests! D'oh!) Que switch accepte les chaînes, alors c'est ce que je vais utiliser. Merci!

113
David Schmitt

Créer un dictionnaire constant réellement compilé au moment de la compilation en C # n’est pas une tâche simple. En fait, aucune des réponses ici ne parvient vraiment à cela.

Il existe cependant une solution qui répond à vos besoins, même si ce n’est pas nécessairement la solution de Nice. N'oubliez pas que, conformément à la spécification C #, les tables de cas de commutation sont compilées dans des tables de saut de hachage constantes. C'est-à-dire que ce sont des dictionnaires constants et non une série d'énoncés if-else. Alors, considérons une déclaration switch-case comme ceci:

switch (myString)
{
   case "cat": return 0;
   case "dog": return 1;
   case "elephant": return 3;
}

C'est exactement ce que vous voulez. Et oui, je sais, c'est moche.

167
Tamas Czinege

Il existe peu de collections immuables dans le cadre actuel. Je peux penser à une option relativement simple dans .NET 3.5:

Utilisez Enumerable.ToLookup() - le Lookup<,> la classe est immuable (mais multivaluée sur le rhs); vous pouvez le faire à partir d'un Dictionary<,> plutôt facilement:

    Dictionary<string, int> ids = new Dictionary<string, int> {
      {"abc",1}, {"def",2}, {"ghi",3}
    };
    ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
    int i = lookup["def"].Single();
36
Marc Gravell
enum Constants
{
    Abc = 1,
    Def = 2,
    Ghi = 3
}

...

int i = (int)Enum.Parse(typeof(Constants), "Def");
14
Richard Poole

Ceci est la chose la plus proche que vous pouvez obtenir à un "Dictionnaire CONST":

public static int GetValueByName(string name)
{
    switch (name)
    {
        case "bob": return 1;
        case "billy": return 2;
        default: return -1;
    }
}

Le compilateur sera suffisamment intelligent pour générer le code le plus propre possible.

10
Timothy Khouri

Si j'utilisais 4.5+ Framework, j'utiliserais ReadOnlyDictionary (également ReadOnly Collection pour les listes) pour faire des mappages/constantes en lecture seule. C'est implémenté de la manière suivante.

static class SomeClass
{
    static readonly ReadOnlyDictionary<string,int> SOME_MAPPING 
        = new ReadOnlyDictionary<string,int>(
            new Dictionary<string,int>()
            {
                { "One", 1 },
                { "Two", 2 }
            }
        )
}        
3
Kram

Pourquoi ne pas utiliser des espaces de noms ou des classes pour imbriquer vos valeurs? C'est peut-être imparfait, mais c'est très propre.

public static class ParentClass
{
    // here is the "dictionary" class
    public static class FooDictionary
    {
        public const string Key1 = "somevalue";
        public const string Foobar = "fubar";
    }
}

Vous pouvez maintenant accéder à .ParentClass.FooDictionary.Key1, etc.

2
Joshua

Il ne semble pas exister d'interface immuable standard pour les dictionnaires. Créer un wrapper semble donc être la seule option raisonnable, malheureusement.

Edit: Marc Gravell a trouvé l’ILookup que j’ai manqué - cela vous permettra au moins d’éviter de créer un nouvel emballage, bien que vous ayez toujours besoin de transformer le dictionnaire avec .ToLookup ().

S'il s'agit d'un besoin limité à un scénario spécifique, il vaut peut-être mieux utiliser une interface davantage orientée vers la logique métier:

interface IActiveUserCountProvider
{
    int GetMaxForServer(string serverName);
}
1
Sander

Je ne sais pas pourquoi personne ne l'a mentionné, mais en C # pour les choses que je ne peux pas affecter const, j'utilise des propriétés statiques en lecture seule.

Exemple:

public static readonly Dictionary<string, string[]> NewDictionary = new Dictionary<string, string[]>()
        {
            { "Reference1", Array1 },
            { "Reference2", Array2 },
            { "Reference3", Array3 },
            { "Reference4", Array4 },
            { "Reference5", Array5 }
        };
0
Suleman