Non noterai una grande differenza di prestazioni tra i due, ma ti consiglio comunque di utilizzare un dizionario perché ti darà un po 'più di flessibilità in futuro.
Per prima cosa, un Enum in C# non può avere automaticamente una classe associata ad esso come in Java, quindi se si desidera associare informazioni aggiuntive con uno stato (Nome completo, Capitale, Abbreviazione postale, ecc.) , creando una classe UnitedState
sarà più semplice raggruppare tutte queste informazioni in una raccolta.
Inoltre, anche se si si pensa che questo valore non cambierà mai, non è perfettamente immutabile. Ad esempio, potresti avere un nuovo requisito per includere i territori. O forse dovrai consentire agli utenti canadesi di vedere i nomi delle province canadesi. Se si considera questa raccolta come qualsiasi altra raccolta di dati (utilizzando un repository per recuperare i valori da essa), in seguito si avrà la possibilità di modificare l'implementazione del repository per estrarre valori da un'origine diversa (database, servizio Web, sessione, ecc.). Le enumerazioni sono molto meno versatili.
Modifica
Per quanto riguarda l'argomento delle prestazioni: Tenete a mente che non sei solo esprimono un Enum per un int: si sta anche eseguendo ToString() su tale enum, che aggiunge un notevole tempo di elaborazione. Si consideri il seguente test:
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);
Risultati:
Enum: 26.4875
Dictionary: 0.7684
Quindi, se le prestazioni sono davvero la vostra preoccupazione principale, un dizionario è sicuramente la strada da percorrere. Tuttavia, stiamo parlando di tempi così veloci che ci sono una mezza dozzina di altre preoccupazioni che vorrei affrontare prima che mi interessasse anche il problema della velocità.
enumerazioni in C# non sono stati progettati per fornire mappature tra i valori e stringhe. Sono stati progettati per fornire valori costanti fortemente tipizzati che è possibile aggirare nel codice. I due vantaggi principali di questo sono:
- avete un indizio in più del compilatore-controllato per aiutarvi ad evitare il passaggio di argomenti nell'ordine sbagliato, ecc
- piuttosto che mettere i valori numerici "magici" (ad esempio "42 ") nel tuo codice, puoi pronunciare" States.Oklahoma ", che rende il tuo codice più leggibile.
A differenza di Java, C# non controlla automaticamente i valori del cast per garantire che essi siano validi (myState = (States)321
), in modo da non si ottiene alcun controllo dati runtime sugli ingressi senza fare manualmente. Se non si dispone del codice che si riferisce esplicitamente agli stati ("States.Oklahoma"), allora non si ottiene alcun valore dalla # 2 sopra. Questo ci lascia con # 1 come l'unica vera ragione per usare le enumerazioni. Se questo è un motivo sufficiente per te, suggerirei di utilizzare le enumerazioni invece degli interi come valori chiave. Quindi, quando hai bisogno di una stringa o di qualche altro valore relativo allo stato, esegui una ricerca del dizionario.
Ecco come lo farei:
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);
}
}
questo modo:
- si arriva a passare i valori intorno fortemente tipizzato che rappresentano uno Stato,
- tua ricerca ottiene fail comportamento veloce se viene fornito un input non valido,
- è possibile modificare facilmente dove risiedono i dati dello stato effettivo in futuro,
- è possibile aggiungere facilmente dati relativi allo stato alla classe State in futuro,
- è possibile aggiungere facilmente nuovi stati, territori, distretti, province o qualsiasi altra cosa in futuro.
- ottenere un nome da un int è ancora circa 15 volte più veloce rispetto a quando si utilizza
Enum.ToString()
.
[grunt]
Perché avrete bisogno di gettare loro? – LukeH
@LukeH: Presumibilmente perché nel database i valori saranno solo numeri interi. –
@Jon: Questo è quello che ho indovinato, ma sarebbe bello ottenere dei chiarimenti dall'OP. – LukeH