Pergunta

O que é a maneira mais eficiente para criar um constante (nunca muda em tempo de execução) mapeamento de strings para ints?

Eu tentei usar um const Dictionary , mas isso não funcionou.

Eu poderia implementar um imutável invólucro com semântica apropriada, mas isso ainda não parece totalmente certo.


Para aqueles que pediram, eu estou implementando IDataErrorInfo em uma classe gerada e estou procurando uma maneira de fazer a pesquisa columnName no meu conjunto de descritores.

Eu não tinha conhecimento (erro de digitação ao testar! D'oh!) Que o interruptor aceita cadeias, então é isso que eu vou usar. Obrigado!

Foi útil?

Solução

A criação de um verdadeiro tempo de compilação gerado dicionário constante em C # não é realmente uma tarefa simples. Na verdade, nenhuma das respostas aqui realmente conseguir isso.

Há uma solução embora que atenda às suas necessidades, embora não necessariamente uma agradável; lembre-se que de acordo com a especificação C #, mesas switch-caso são compilados para tabelas de hash salto constantes. Ou seja, eles são dicionários constantes, não uma série de declarações if-else. Por isso, considero uma instrução switch-caso como este:

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

Este é exatamente o que você quer. E sim, eu sei, é feio.

Outras dicas

Há pouquíssimas coleções imutáveis ??no quadro atual. Não consigo pensar em uma opção relativamente livre de dor em .NET 3.5:

Use Enumerable.ToLookup() - o Lookup<,> classe é imutável (mas multi- valorizado nas rhs); você pode fazer isso a partir de um Dictionary<,> com bastante facilidade:

    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");

Esta é a coisa mais próxima que você pode chegar a um "CONST dicionário":

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

O compilador será inteligente o suficiente para construir o código o mais limpo possível.

Se estiver usando 4.5+ Framework eu usaria ReadOnlyDictionary (também Coleção ReadOnly para listas) para fazer somente leitura mapeamentos / constantes. Ele é implementado da seguinte forma.

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

Por que não usar namespaces ou classes para aninhar seus valores? Pode ser imperfeito, mas é muito limpo.

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

Agora você pode acessar .ParentClass.FooDictionary.Key1, etc.

Não parece ser qualquer interface imutável padrão para dicionários, criando assim um invólucro parece ser a única opção razoável, infelizmente.

Editar :. Marc Gravell encontrou o iLookup que eu perdi - que irá permitir-lhe, pelo menos, evitar a criação de um novo invólucro, embora você ainda precisa transformar o dicionário com .ToLookup ()

Se esta é uma necessidade restrito a um cenário específico, você pode ser melhor fora com uma interface mais empresarial orientada a lógica:

interface IActiveUserCountProvider
{
    int GetMaxForServer(string serverName);
}

Por que não:

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>>(); }
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top