Enum in String konvertieren

163

Welches ist die bevorzugte Methode zum Konvertieren einer Aufzählung in einen String in .NET 3.5?

  • Enum.GetName
  • Enum.Format
  • ToString

Warum sollte ich eines davon den anderen vorziehen? Leistung man besser?

Eric Weilnau
quelle
10
Ich habe gesucht und konnte kein Duplikat finden. Wenn Sie einen Link angeben können, werde ich diese Frage löschen.
Eric Weilnau
1
Manchmal ist die Verwendung einer switch-Anweisung nicht die beste Vorgehensweise (wenn Sie große Aufzählungen haben). Sie können stattdessen Dict <> verwenden
Guy L
1
Wenn Sie eine bessere Leistung wünschen, können Sie die in diesem Artikel beschriebene Klasse codeproject.com/KB/dotnet/enum.aspx verwenden . Die Verwendung sieht folgendermaßen aus: Enum <YourEnum> .ToString (yourValue) oder Enum <YourEnum> .ToString ((int) yourValue)
ideafixxxer
5
Die Codierung, um die Dotfuscation nicht zu unterbrechen, ist der Inbegriff des Schwanzes, mit dem der Hund wedelt. SW-Produzenten denken nicht: "Machen wir eine großartige App, damit Dotfuscator etwas zu tun hat." Dofuscator dient zur Erleichterung der SW-Entwicklung. Wenn es das nicht kann ... kann es!
Micahhoover

Antworten:

125

Ab C # 6 ist der neue nameofOperator der beste Weg, um den Namen einer Aufzählung zu erhalten :

nameof(MyEnum.EnumValue);

// Ouputs
> "EnumValue"

Dies funktioniert zur Kompilierungszeit, wobei die Aufzählung im kompilierten Ergebnis durch die Zeichenfolge ersetzt wird. Dies bedeutet wiederum, dass dies der schnellstmögliche Weg ist.

Jede Verwendung von Aufzählungsnamen beeinträchtigt die Verschleierung des Codes, wenn Sie die Verschleierung von Aufzählungsnamen für sinnvoll oder wichtig halten - das ist wahrscheinlich eine ganz andere Frage.

Keith
quelle
11
Dies verdient mehr Aufmerksamkeit. Ungeachtet der offensichtlichen Einschränkung, dh der Anforderung für die Eingabe zur Kompilierungszeit. Meiner Meinung nach sollte dies nach Möglichkeit bevorzugt werden . 'Umbenennen' und 'Alle Referenzen finden' berücksichtigen dies ebenfalls und vermeiden möglicherweise magische Zeichenfolgen und doppelte Konstanten.
Timo
1
Also denke ich, dass es nicht funktioniert, wenn der Enum-Wert zur Laufzeit definiert ist? Beispiel: MyEnum variableEnum; variableEnum = setEnumValueMethod (); nameof (variableEnum);
Maxter
1
@ Maxter nein, wie nameof(variableEnum)es sein wird "variableEnum". Es gibt (zum Zeitpunkt der Erstellung) den Namen des Felds / der Eigenschaft / des Parameters / der Variablen wieder, nicht den Wert .
Keith
Ihr. funktioniert leider nicht, wenn Sie dies tun: var someEnumvalue = SomeEnum.FooBar; nameof (someEnumvalue);
Squibly
@Squibly ja, das wird wieder "someEnumValue", während Sie müßten nameof(SomeEnum.FooBar)bekommen "FooBar".
Keith
93

Arbeitet für unser Projekt ...

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);
}
Sumtraveller
quelle
7
Enum.GetName verwendet den Wert als Objektargument. Dies bedeutet, dass der Wert eingerahmt wird und CPU-Ressourcen für die Zuordnung und die Speicherbereinigung verschwendet werden. Wenn dies viel Zeit in Anspruch nimmt, hat Enum.GetName einen viel geringeren Durchsatz als das Zwischenspeichern der Werte in einem Wörterbuch und das Suchen nach dem Namen dort.
Lief
@Ran also was ist die Lösung, die stattdessen verwendet werden soll?
Shaijut
Dies sollte die Antwort sein
Squibly
macht mein Projekt langsamer. toString () ist schneller.
d2k2
29

In meinen Tests Enum.GetNamewar schneller und mit ordentlichem Abstand. Interne ToStringAnrufe Enum.GetName. Aus dem Quellcode für .NET 4.0:

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

Ich kann nicht sagen, dass dies der Grund ist, aber Tests besagen, dass einer schneller ist als der andere. Beide Anrufe beinhalten Boxen (tatsächlich handelt es sich um Reflexionsanrufe, Sie rufen im Wesentlichen Feldnamen ab) und können für Ihren Geschmack langsam sein.

Testaufbau : Aufzählung mit 8 Werten, Nr. Anzahl der Iterationen = 1000000

Ergebnis : Enum.GetName => 700 ms, ToString => 2000 ms

Wenn die Geschwindigkeit nicht spürbar ist, würde es mich nicht interessieren und verwenden, ToStringda es einen viel saubereren Anruf bietet. Kontrast

Enum.GetName(typeof(Bla), value)

mit

value.ToString()
nawfal
quelle
25

Enum.GetName (...)

Dies ist die eleganteste Methode, die dafür gedacht ist.

var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);

Obwohl ich keine Probleme mit Anrufen sehe, .ToString()da es einfach kürzer ist.

var enumValueString = MyEnum.MyValue.ToString();

Mit der neuen C # 6-Syntax können Sie Folgendes verwenden:

nameof(MyEnum.MyValue)
Andrei
quelle
20

All dies führt intern zu einer aufgerufenen Methode InternalGetValueAsString. Der Unterschied zwischen ToStringund GetNamewäre, dass GetNamezuerst einige Dinge überprüft werden müssen:

  1. Der eingegebene Typ ist nicht null.
  2. Der Typ, den Sie eingegeben haben, ist tatsächlich eine Aufzählung.
  3. Der Wert, den Sie übergeben haben, ist nicht null.
  4. Der übergebene Wert ist von einem Typ, den eine Aufzählung tatsächlich als zugrunde liegenden Typ verwenden kann, oder vom Typ der Aufzählung selbst. Es verwendet GetTypeden Wert, um dies zu überprüfen.

.ToStringSie müssen sich über keines der oben genannten Probleme Gedanken machen, da es für eine Instanz der Klasse selbst und nicht für eine übergebene Version aufgerufen wird, da die .ToStringMethode nicht dieselben Überprüfungsprobleme aufweist Als statische Methode würde ich schließen, dass dies .ToStringder schnellste Weg ist, um den Wert als Zeichenfolge zu erhalten.

David Morton
quelle
2
Wo hast du diese überprüft? Was war die Baugruppenversion? Ich bekomme sehr unterschiedliche Ergebnisse.
Nawfal
17

Das Beste, was ich finden kann, ist diese nicht verwandte Frage zu MSDN , die ein XML-Snippet enthält, das diese Frage beantwortet. Jede dieser Methoden hat den gleichen Fehler: Sie rufen auf enum.toString(), was bei Verwendung von Dotfuscation nicht richtig funktioniert . Andere Bedenken scheinen sich auf das indirekte Boxen (GetName und Format) zu beziehen. Leider kann ich keine Leistungsgründe für die Verwendung der oben genannten finden.

Paraphrasierung aus dem XML-Snippet ,

Das Übergeben einer Box-Enumeration an string.Format () oder eine andere Funktion kann enum.ToString()zum Aufruf führen. Dies führt beim Dotfuscating zu Problemen. Sie sollten nicht verwenden enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format()oder enum.Parse()eine ENUM in eine Zeichenfolge zu konvertieren. Verwenden Sie stattdessen eine switch-Anweisung und internationalisieren Sie die Namen bei Bedarf.

jpaugh
quelle
16

Enum.GetName()

Format()ist wirklich nur ein Wrapper GetName()mit einigen Formatierungsfunktionen (oder InternalGetValueAsString()um genau zu sein). ToString()ist so ziemlich das gleiche wie Format(). Ich denke, es GetName()ist die beste Option, da es völlig offensichtlich ist, was es für jeden tut, der die Quelle liest.

Tamas Czinege
quelle
8

Ich erstelle eine Erweiterungsmethode "Beschreibung" und hänge sie an die Aufzählung an, damit ich eine wirklich benutzerfreundliche Benennung erhalten kann, die Leerzeichen und Groß- und Kleinschreibung enthält. Ich habe es nie gemocht, den Enum-Wert selbst als anzeigbaren Text zu verwenden, da wir Entwickler ihn verwenden, um besser lesbaren Code zu erstellen. Es ist nicht für die Anzeige der Benutzeroberfläche vorgesehen. Ich möchte in der Lage sein, die Benutzeroberfläche zu ändern, ohne die Aufzählungen zu ändern.

Tänze mit Bambus
quelle
6

Ich weiß nicht, was die "bevorzugte" Methode ist (fragen Sie 100 Leute und holen Sie sich 100 verschiedene Meinungen), aber tun Sie, was am einfachsten ist und was funktioniert. GetNamefunktioniert, erfordert aber viel mehr Tastenanschläge. ToString()scheint den Job sehr gut zu machen.

Perry Neal
quelle
1

Für VB-Liebhaber:

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

Das würde auch funktionieren.

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

ToString()liefert das offensichtlichste Ergebnis aus Sicht der Lesbarkeit während der VerwendungEnum.GetName() etwas mehr mentales Parsen erfordert, um schnell zu verstehen, was versucht wird (es sei denn, Sie sehen das Muster ständig).

Aus reiner Sicht der Leistung Enum.GetName()ist es besser , wie bereits in der Antwort von @ nawfal angegeben .

Wenn Leistung jedoch wirklich Ihr Ziel ist, ist es noch besser, vorher nachzuschlagen (mithilfe eines Wörterbuchs oder einer anderen Zuordnung).

In C ++ / CLI würde dies so aussehen

Dictionary<String^, MyEnum> mapping;
for each (MyEnum field in Enum::GetValues(MyEnum::typeid))
{
    mapping.Add(Enum::GetName(MyEnum::typeid), field);
}

Vergleich mit einer Aufzählung von 100 Elementen und 1000000 Iterationen:

Enum.GetName: ~ 800 ms
.ToString (): ~ 1600 ms
Wörterbuchzuordnung: ~ 250 ms

John Go-Soco
quelle
-2

Einfach: Namen in eine Liste auflisten:

List<String> NameList = Enum.GetNames(typeof(YourEnumName)).Cast<string>().ToList()
Brian
quelle
Hallo @Brian, ich glaube nicht, dass Sie die Ausgabe von GetNames ()
Nic