No notará una gran diferencia en el rendimiento entre los dos, pero aún así recomendaría usar un diccionario porque le dará un poco más de flexibilidad en el futuro.
Por un lado, un Enum en C# no puede tener automáticamente una clase asociada como en Java, por lo que si desea asociar información adicional con un estado (Nombre completo, Capital, Abreviatura postal, etc.) , la creación de una clase UnitedState
facilitará el empaquetado de toda esa información en una sola colección.
Además, a pesar de que piensa en este valor nunca cambiará, no es perfectamente inmutable. Posiblemente podría tener un nuevo requisito para incluir Territorios, por ejemplo. O quizás deba permitir que los usuarios canadienses vean los nombres de las provincias canadienses en su lugar. Si trata esta colección como cualquier otra colección de datos (usando un repositorio para recuperar valores de ella), más adelante tendrá la opción de cambiar su implementación de repositorio para extraer valores de una fuente diferente (Base de datos, Servicio web, Sesión, etc.) Los mensajes son mucho menos versátiles.
Editar
En cuanto al argumento de rendimiento: Tenga en cuenta que no estás solo emitan un Enum de un int: también se está ejecutando ToString() en esa enumeración, lo que añade un considerable tiempo de procesamiento. Considere la siguiente prueba:
const int C = 10000;
int[] ids = new int[C];
string[] names = new string[C];
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i< C; i++)
{
var id = (i % 50) + 1;
names[i] = ((States)id).ToString();
}
sw.Stop();
Console.WriteLine("Enum: " + sw.Elapsed.TotalMilliseconds);
var namesById = Enum.GetValues(typeof(States)).Cast<States>()
.ToDictionary(s => (int) s, s => s.ToString());
sw.Restart();
for (int i = 0; i< C; i++)
{
var id = (i % 50) + 1;
names[i] = namesById[id];
}
sw.Stop();
Console.WriteLine("Dictionary: " + sw.Elapsed.TotalMilliseconds);
Resultados:
Enum: 26.4875
Dictionary: 0.7684
Así que si realmente el rendimiento es su principal preocupación, un diccionario es definitivamente el camino a seguir. Sin embargo, estamos hablando de tiempos tan rápidos aquí que hay media docena de otras preocupaciones que abordaría antes de preocuparme por el problema de la velocidad.
Las enumeraciones en C# no se diseñaron para proporcionar asignaciones entre valores y cadenas. Fueron diseñados para proporcionar valores constantes fuertemente tipados que puede pasar en el código. Las dos principales ventajas de esto son:
- Usted tiene una pista compilador comprobado extra para ayudar a evitar el paso de argumentos en el orden equivocado, etc.
- en lugar de poner "mágicas" valores numéricos (por ejemplo, "42 ") en su código, puede decir" States.Oklahoma ", que hace que su código sea más legible.
diferencia de Java, C# no comprueba automáticamente los valores de elenco para asegurarse de que son válidos (myState = (States)321
), por lo que no reciben ninguna verificación de datos durante la ejecución de los insumos sin hacerlo a mano. Si no tiene un código que se refiera explícitamente a los estados ("States.Oklahoma"), entonces no obtiene ningún valor del # 2 anterior. Eso nos deja con el # 1 como la única razón real para usar enumeraciones. Si este es un buen motivo para usted, le sugiero que utilice las enumeraciones en lugar de los puntos como valores clave. Luego, cuando necesite una cadena u otro valor relacionado con el estado, realice una búsqueda en el diccionario.
Así es como yo lo haría:
public enum StateKey{
AL = 1,AK,AS,AZ,AR,CA,CO,CT,DE,DC,FM,FL,GA,GU,
HI,ID,IL,IN,IA,KS,KY,LA,ME,MH,MD,MA,MI,MN,MS,
MO,MT,NE,NV,NH,NJ,NM,NY,NC,ND,MP,OH,OK,OR,PW,
PA,PR,RI,SC,SD,TN,TX,UT,VT,VI,VA,WA,WV,WI,WY,
}
public class State
{
public StateKey Key {get;set;}
public int IntKey {get {return (int)Key;}}
public string PostalAbbreviation {get;set;}
}
public interface IStateRepository
{
State GetByKey(StateKey key);
}
public class StateRepository : IStateRepository
{
private static Dictionary<StateKey, State> _statesByKey;
static StateRepository()
{
_statesByKey = Enum.GetValues(typeof(StateKey))
.Cast<StateKey>()
.ToDictionary(k => k, k => new State {Key = k, PostalAbbreviation = k.ToString()});
}
public State GetByKey(StateKey key)
{
return _statesByKey[key];
}
}
public class Foo
{
IStateRepository _repository;
// Dependency Injection makes this class unit-testable
public Foo(IStateRepository repository)
{
_repository = repository;
}
// If you haven't learned the wonders of DI, do this:
public Foo()
{
_repository = new StateRepository();
}
public void DoSomethingWithAState(StateKey key)
{
Console.WriteLine(_repository.GetByKey(key).PostalAbbreviation);
}
}
esta manera:
- se llega a pasar en torno a valores de tipo fuerte que representan un estado,
- su búsqueda obtiene fail comportamiento rápido si se le da una entrada no válida,
- puede cambiar fácilmente dónde residen los datos de estado reales en el futuro,
- puede agregar fácilmente datos relacionados con el estado a la clase State en el futuro,
- puede agregar fácilmente nuevos estados, territorios, distritos, provincias o cualquier otra cosa en el futuro.
- obtener un nombre de un int es todavía aproximadamente 15 veces más rápido que cuando se usa
Enum.ToString()
.
[gruñido]
¿Por qué necesitará echarlas? – LukeH
@LukeH: Presumiblemente porque en la base de datos los valores serán enteros. –
@Jon: Eso es lo que supuse, pero sería bueno obtener aclaraciones del OP. – LukeH