Converti Enum in String


163

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?


10
Ho cercato e non sono riuscito a trovare un duplicato. Se è possibile fornire un collegamento, eliminerò questa domanda.
Eric Weilnau,

1
a volte, usare un'istruzione switch non è la migliore pratica (quando hai grandi enumerazioni) puoi usare Dict <> invece
Guy L

1
Se desideri prestazioni migliori, puoi utilizzare la classe descritta in questo articolo codeproject.com/KB/dotnet/enum.aspx . L'utilizzo sarà simile a questo Enum <YourEnum> .ToString (yourValue) o Enum <YourEnum> .ToString ((int) yourValue)
ideafixxxer

5
Codificare per non spezzare la dotfuscation è l'epitome della coda che scuote il cane. I produttori di software SW non pensano: "Facciamo un'ottima app in modo che Dotfuscator abbia qualcosa da fare". Dofuscator esiste per aiutare a facilitare lo sviluppo SW. Se non può farlo ... può farlo!
micahhoover,

Risposte:


127

A partire da C # 6 il modo migliore per ottenere il nome di un enum è il nuovo nameofoperatore:

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.


11
Questo merita più attenzione. Nonostante l'ovvia limitazione, vale a dire il requisito per l'input in fase di compilazione. Secondo me questo dovrebbe essere preferito ogni volta che è possibile . Anche 'Rinomina' e 'trova tutti i riferimenti' ne tengono conto, evitando potenzialmente stringhe magiche e costanti duplicate.
Timo,

1
Quindi immagino che non funzionerà quando il valore enum è definito in fase di esecuzione? Esempio: MyEnum variabileEnum; variabileEnum = setEnumValueMethod (); nameof (variableEnum);
Maxter,

1
@Maxter no, come nameof(variableEnum)sarà "variableEnum". Riflette (al momento della compilazione) il nome del campo / proprietà / parametro / variabile non il valore .
Keith,

voi. purtroppo non funziona se si esegue questa operazione: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
Squably

1
@Sicuramente sì, questo tornerà "someEnumValue", mentre dovresti nameof(SomeEnum.FooBar)ottenere "FooBar".
Keith,

93

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

7
Enum.GetName accetta il valore come argomento di un oggetto. Ciò significa che il valore verrà inscatolato e questo sprecherà risorse della CPU per l'allocazione e la garbage collection. Se ciò viene fatto per molto tempo, Enum.GetName avrà un throughput molto inferiore rispetto alla memorizzazione nella cache dei valori in un dizionario e alla ricerca del nome lì.
Ha funzionato

@Ran quindi qual è la soluzione, quale utilizzare invece?
Shaijut,

Questa dovrebbe essere la risposta
Squably

rende il mio progetto più lento. toString () è più veloce.
d2k2,

29

Nei miei test, è Enum.GetNamestato più veloce e con margine decente. ToStringChiama 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 ToStringpoiché offre una chiamata molto più pulita. Contrasto

Enum.GetName(typeof(Bla), value)

con

value.ToString()

25

Enum.GetName (...)

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)

20

Tutti questi finiscono internamente per chiamare un metodo chiamato InternalGetValueAsString. La differenza tra ToStringe GetNamesarebbe che GetNamedeve prima verificare alcune cose:

  1. Il tipo inserito non è nullo.
  2. Il tipo che hai inserito è, in effetti, un elenco.
  3. Il valore che hai passato non è nullo.
  4. Il valore passato è di un tipo che un'enumerazione può effettivamente utilizzare come tipo sottostante o del tipo dell'enumerazione stessa. Utilizza GetTypeil valore per verificarlo.

.ToStringnon 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 .ToStringmetodo non ha gli stessi problemi di verifica come metodi statici, concluderei che .ToStringè il modo più veloce per ottenere il valore come stringa.


2
dove hai controllato questi? Qual era la versione dell'assembly? Ottengo risultati molto diversi.
nawfal,

17

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 usare enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()o enum.Parse()per convertire un enum in una stringa. Utilizzare invece un'istruzione switch e, se necessario, anche internazionalizzare i nomi.


16

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.


8

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.


6

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. GetNamefunziona ma richiede molti più tasti. ToString()sembra fare molto bene il lavoro.


1

Per gli appassionati di VB:

EnumStringValue = System.Enum.GetName(GetType(MyEnum), MyEnumValue)

0

Anche questo funzionerebbe.

    List<string> names = Enum.GetNames(typeof(MyEnum)).ToList();

0

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


-3

Semplice: enumare i nomi in un elenco:

List<String> NameList = Enum.GetNames(typeof(YourEnumName)).Cast<string>().ToList()

Ciao @Brian, non credo che devi trasmettere l'output di GetNames ()
Nic
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.