Création d'un dictionnaire constant en C#

Quelle est la manière la plus efficace de créer une constante (ne change jamais à l'exécution) de la correspondance de string s à int s?

j'ai essayé d'utiliser un const Dictionary , mais ça n'a pas marché.

je pourrais implémenter un immuable wrapper avec la sémantique appropriée, mais cela ne semble toujours pas tout à fait juste.


pour ceux qui ont demandé, je implémente IDataErrorInfo dans une classe générée et je suis à la recherche d'un moyen de faire la recherche columnnname dans mon tableau de descripteurs.

Je n'étais pas au courant (typo lors des tests! oh pinaise! ce commutateur accepte les cordes, donc c'est ce que je vais utiliser. Merci!

99
demandé sur David Schmitt 2008-11-06 12:38:22

7 réponses

la création d'un dictionnaire constant généré en temps de compilation dans C# n'est pas vraiment une tâche simple. En fait, aucune des réponses n'y parvient vraiment.

il y a cependant une solution qui répond à vos exigences, mais pas nécessairement une bonne; rappelez-vous que selon la spécification C#, les tables switch-case sont compilées à des tables de saut de hachage constant. C'est-à-dire qu'ils sont des dictionnaires constants, et non une série de déclarations SI-AUTREMENT. Ainsi, considérer une déclaration comme celle-ci:

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.

142
répondu Tamas Czinege 2010-04-18 16:58:22

il y a très peu de collections immuables dans le cadre actuel. Je peux penser à une option relativement sans douleur dans .NET 3.5:

utiliser Enumerable.ToLookup() - la classe Lookup<,> est immuable (mais Multi-valorisé sur le rhs); vous pouvez le faire à partir d'un Dictionary<,> assez 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();
32
répondu Marc Gravell 2008-11-06 09:51:32
enum Constants
{
    Abc = 1,
    Def = 2,
    Ghi = 3
}

...

int i = (int)Enum.Parse(typeof(Constants), "Def");
13
répondu Richard Poole 2008-11-06 10:56:09

C'est la chose la plus proche que vous pouvez obtenir à un "CONST Dictionary":

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

le compilateur sera assez intelligent pour construire le code aussi propre que possible.

9
répondu Timothy Khouri 2008-11-06 10:39:12

il ne semble pas y avoir d'interface standard immuable pour les dictionnaires, donc créer un wrapper semble être la seule option raisonnable, malheureusement.

Edit : Marc Gravell a trouvé L'ILookup que j'ai manqué - qui vous permettra au moins d'éviter de créer un nouvel emballage, bien que vous devez encore transformer le dictionnaire avec .ToLookup().

Si c'est un besoin limité à un scénario spécifique, vous pourriez être

interface IActiveUserCountProvider
{
    int GetMaxForServer(string serverName);
}
1
répondu Sander 2008-11-06 09:48:28

pourquoi ne pas utiliser des namespaces ou des classes pour intégrer vos valeurs? Il peut être imparfait, mais il 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";
    }
}

maintenant vous pouvez y accéder .Myclass.FooDictionary.Key1, etc.

1
répondu Joshua 2018-04-10 17:01:05

pourquoi pas:

public class MyClass
{
    private Dictionary<string, int> _myCollection = new Dictionary<string, int>() { { "A", 1 }, { "B", 2 }, { "C", 3 } };

    public IEnumerable<KeyValuePair<string,int>> MyCollection
    {
        get { return _myCollection.AsEnumerable<KeyValuePair<string, int>>(); }
    }
}
-1
répondu 2010-07-27 12:48:25