Crear un diccionario constante en C#


¿Cuál es la forma más eficiente de crear un mapeo constante (nunca cambia en tiempo de ejecución) de string s a int s?

He intentado usar un diccionario const , pero eso no funcionó.

Podría implementar un envoltura inmutable con la semántica apropiada, pero eso todavía no parece totalmente correcto.


Para aquellos que han pedido, estoy implementando IDataErrorInfo en una clase generada y estoy buscando una manera de hacer que la Búsqueda de ColumnName en mi matriz de descriptores.

No estaba consciente (error tipográfico al probar! d'oh! ese interruptor acepta cadenas, así que eso es lo que voy a usar. ¡Gracias!

Author: David Schmitt, 2008-11-06

7 answers

Crear un diccionario constante realmente generado en tiempo de compilación en C# no es realmente una tarea sencilla. En realidad, ninguna de las respuestas aquí realmente lograrlo.

Sin embargo, hay una solución que cumple con sus requisitos, aunque no necesariamente una buena; recuerde que de acuerdo con la especificación de C#, las tablas switch-case se compilan en tablas de salto de hash constante. Es decir, son diccionarios constantes, no una serie de sentencias if-else. Así que considere una sentencia switch-case así:

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

Esto es exactamente lo que quieres. Y sí, lo sé, es feo.

 142
Author: Tamas Czinege,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-18 16:58:22

Hay muy pocas colecciones inmutables en el marco actual. Puedo pensar en una opción relativamente libre de dolor en. NET 3.5:

Use Enumerable.ToLookup() - el Lookup<,> la clase es inmutable (pero multi-valorada en el rhs); puedes hacer esto desde un Dictionary<,> bastante fácilmente:

    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
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-06 09:51:32
enum Constants
{
    Abc = 1,
    Def = 2,
    Ghi = 3
}

...

int i = (int)Enum.Parse(typeof(Constants), "Def");
 13
Author: Richard Poole,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-06 10:56:09

Esto es lo más parecido a un "Diccionario CONST":

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

El compilador será lo suficientemente inteligente como para construir el código lo más limpio posible.

 9
Author: Timothy Khouri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-06 10:39:12

No parece haber ninguna interfaz estándar inmutable para diccionarios, por lo que crear un wrapper parece ser la única opción razonable, desafortunadamente.

Editar : Marc Gravell encontró el ILookup que me perdí - que le permitirá al menos evitar la creación de una nueva envoltura, aunque todavía necesita transformar el Diccionario con .ToLookup().

Si esta es una necesidad limitada a un escenario específico, podría estar mejor con una lógica de negocios más orientada interfaz:

interface IActiveUserCountProvider
{
    int GetMaxForServer(string serverName);
}
 1
Author: Sander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-06 09:48:28

¿Por qué no usar espacios de nombres o clases para anidar sus valores? Puede ser imperfecto, pero es muy limpio.

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

Ahora puedes acceder .Clase de padres.FooDictionary.Key1, etc.

 1
Author: Joshua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-10 17:01:05

Por qué no:

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
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-27 12:48:25