Qual è il modo preferito per convertire un Enum in una stringa in .NET 3.5?
- Enum.GetName
- Enum.Format
- Accordare
Perché dovrei preferire uno di questi rispetto agli altri? Uno si comporta meglio?
Qual è il modo preferito per convertire un Enum in una stringa in .NET 3.5?
Perché dovrei preferire uno di questi rispetto agli altri? Uno si comporta meglio?
Risposte:
A partire da C # 6 il modo migliore per ottenere il nome di un enum è il nuovo nameof
operatore:
nameof(MyEnum.EnumValue);
// Ouputs
> "EnumValue"
Funziona in fase di compilazione, con l'enum che viene sostituito dalla stringa nel risultato compilato, il che a sua volta significa che questo è il modo più veloce possibile.
Qualsiasi uso dei nomi di enum interferisce con l'offuscamento del codice, se consideri che l'offuscamento dei nomi di enum sia utile o importante - questa è probabilmente un'altra questione.
nameof(variableEnum)
sarà "variableEnum"
. Riflette (al momento della compilazione) il nome del campo / proprietà / parametro / variabile non il valore .
"someEnumValue"
, mentre dovresti nameof(SomeEnum.FooBar)
ottenere "FooBar"
.
Funziona per il nostro progetto ...
public static String convertToString(this Enum eff)
{
return Enum.GetName(eff.GetType(), eff);
}
public static EnumType converToEnum<EnumType>(this String enumValue)
{
return (EnumType) Enum.Parse(typeof(EnumType), enumValue);
}
Nei miei test, è Enum.GetName
stato più veloce e con margine decente. ToString
Chiama internamente Enum.GetName
. Dalla fonte per .NET 4.0, gli elementi essenziali:
public override String ToString()
{
return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
}
private static String InternalFormat(RuntimeType eT, Object value)
{
if (!eT.IsDefined(typeof(System.FlagsAttribute), false))
{
String retval = GetName(eT, value); //<== the one
if (retval == null)
return value.ToString();
else
return retval;
}
else
{
return InternalFlagsFormat(eT, value);
}
}
Non posso dire che questo sia il motivo, ma i test affermano che uno è più veloce dell'altro. Entrambe le chiamate coinvolgono il pugilato (in realtà sono chiamate di riflessione, essenzialmente stai recuperando i nomi dei campi) e possono essere lente per i tuoi gusti.
Configurazione del test : enum con 8 valori, n. di iterazioni = 1000000
Risultato : Enum.GetName => 700 ms, ToString => 2000 ms
Se la velocità non è evidente, non mi importerebbe e non uso ToString
poiché offre una chiamata molto più pulita. Contrasto
Enum.GetName(typeof(Bla), value)
con
value.ToString()
Questo è il metodo più elegante che è pensato per questo.
var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);
Anche se non vedo alcun problema con la chiamata .ToString()
in quanto è semplicemente più breve.
var enumValueString = MyEnum.MyValue.ToString();
Con la nuova sintassi C # 6 puoi usare:
nameof(MyEnum.MyValue)
Tutti questi finiscono internamente per chiamare un metodo chiamato InternalGetValueAsString
. La differenza tra ToString
e GetName
sarebbe che GetName
deve prima verificare alcune cose:
GetType
il valore per verificarlo..ToString
non deve preoccuparsi di nessuno di questi problemi di cui sopra, perché viene chiamato su un'istanza della classe stessa e non su una versione passata, quindi, a causa del fatto che il .ToString
metodo non ha gli stessi problemi di verifica come metodi statici, concluderei che .ToString
è il modo più veloce per ottenere il valore come stringa.
Il migliore che posso trovare è questa domanda non correlata su MSDN , che contiene uno snippet XML che risponde a questa domanda. Uno di questi metodi condivide lo stesso difetto: chiamano enum.toString()
, che non funziona correttamente quando si utilizza Dotfuscation . Altre preoccupazioni sembrano riguardare il pugilato indiretto (GetName e Format). Sfortunatamente, non riesco a trovare alcun motivo di prestazioni per l'utilizzo di uno dei precedenti.
Parafrasando dallo snippet xml ,
Passare un enum inscatolato a string.Format () o qualsiasi altra funzione può comportare la
enum.ToString()
chiamata. Ciò causerà problemi durante Dotfuscating. Non si deve usareenum.ToString()
,enum.GetNames()
,enum.GetName()
,enum.Format()
oenum.Parse()
per convertire un enum in una stringa. Utilizzare invece un'istruzione switch e, se necessario, anche internazionalizzare i nomi.
Enum.GetName()
Format()
è davvero solo un involucro in giro GetName()
con alcune funzionalità di formattazione (o InternalGetValueAsString()
per essere esatti). ToString()
è praticamente lo stesso di Format()
. Penso che GetName()
sia l'opzione migliore poiché è del tutto ovvio cosa fa per chiunque legga la fonte.
Creo un metodo di estensione "Descrizione" e lo allego all'enum in modo da poter ottenere una denominazione veramente intuitiva che includa spazi e case. Non mi è mai piaciuto usare il valore enum stesso come testo visualizzabile perché è qualcosa che gli sviluppatori usano per creare codice più leggibile. Non è destinato a scopi di visualizzazione dell'interfaccia utente. Voglio essere in grado di cambiare l'interfaccia utente senza passare e cambiare enum dappertutto.
Non so quale sia il metodo "preferito" (chiedi a 100 persone e ottieni 100 opinioni diverse) ma faccio ciò che è più semplice e ciò che funziona. GetName
funziona ma richiede molti più tasti. ToString()
sembra fare molto bene il lavoro.
ToString()
dà il risultato più ovvio dal punto di vista della leggibilità, mentre l'utilizzo Enum.GetName()
richiede un po 'più di analisi mentale per capire rapidamente cosa sta cercando di fare (a meno che non si veda sempre lo schema).
Da un puro punto di vista delle prestazioni, come già indicato nella risposta di @ nawfal, Enum.GetName()
è meglio.
Se le prestazioni sono davvero il tuo obiettivo, sarebbe ancora meglio fornire una ricerca in anticipo (usando un dizionario o qualche altra mappatura).
In C ++ / CLI, questo sarebbe simile
Dictionary<String^, MyEnum> mapping;
for each (MyEnum field in Enum::GetValues(MyEnum::typeid))
{
mapping.Add(Enum::GetName(MyEnum::typeid), field);
}
Confronto usando un enum di 100 elementi e 1000000 iterazioni:
Enum.GetName: ~ 800ms
.ToString (): ~ 1600ms
Mappatura del dizionario: ~ 250ms