Question

Quel est le moyen le plus efficace de créer un mappage constant (qui ne change jamais au moment de l'exécution) de string s sur int s?

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

Je pourrais implémenter un encapsuleur immuable avec une sémantique appropriée, mais cela ne semble toujours pas totalement correct.

Pour ceux qui l'ont demandé, j'implémente IDataErrorInfo dans une classe générée et 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 en testant! d'oh!) que switch accepte les chaînes, alors c'est ce que je vais utiliser. Merci!

Était-ce utile?

La solution

La création en C # d'un dictionnaire constant réellement généré lors de la compilation n'est pas une tâche simple. En fait, aucune des réponses ici ne parvient vraiment à cela.

Il existe une solution qui répond à vos besoins, mais pas nécessairement agréable. 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érez une instruction 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.

Autres conseils

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

Utilisez Enumerable.ToLookup() - la classe Lookup<,> est immuable (mais multi-évalué sur le rhs); vous pouvez le faire depuis 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();
enum Constants
{
    Abc = 1,
    Def = 2,
    Ghi = 3
}

...

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

C’est la chose la plus proche que vous puissiez obtenir d’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.

Si vous utilisez 4.5+ Framework, j'utiliserais ReadOnlyDictionary (également ReadOnly Collection pour les listes) pour effectuer des mappages / constantes en lecture seule. Sa mise en œuvre est la suivante.

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

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.

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

Modifier : Marc Gravell a trouvé l'ILookup que j'ai manquée. Cela vous permettra au moins d'éviter de créer un nouvel emballage, même si vous devez toujours 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);
}

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>>(); }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top