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.
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".
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:
publicoverrideStringToString(){returnEnum.InternalFormat((RuntimeType)GetType(),GetValue());}privatestaticStringInternalFormat(RuntimeType eT,Objectvalue){if(!eT.IsDefined(typeof(System.FlagsAttribute),false)){String retval =GetName(eT,value);//<== the oneif(retval ==null)returnvalue.ToString();elsereturn retval;}else{returnInternalFlagsFormat(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
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:
Der eingegebene Typ ist nicht null.
Der Typ, den Sie eingegeben haben, ist tatsächlich eine Aufzählung.
Der Wert, den Sie übergeben haben, ist nicht null.
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.
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.
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.
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.
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.
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.
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
Antworten:
Ab C # 6 ist der neue
nameof
Operator der beste Weg, um den Namen einer Aufzählung zu erhalten :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.
quelle
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 ."someEnumValue"
, während Sie müßtennameof(SomeEnum.FooBar)
bekommen"FooBar"
.Arbeitet für unser Projekt ...
quelle
In meinen Tests
Enum.GetName
war schneller und mit ordentlichem Abstand. InterneToString
AnrufeEnum.GetName
. Aus dem Quellcode für .NET 4.0: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.
Wenn die Geschwindigkeit nicht spürbar ist, würde es mich nicht interessieren und verwenden,
ToString
da es einen viel saubereren Anruf bietet. Kontrastmit
quelle
Enum.GetName (...)
Dies ist die eleganteste Methode, die dafür gedacht ist.
Obwohl ich keine Probleme mit Anrufen sehe,
.ToString()
da es einfach kürzer ist.Mit der neuen C # 6-Syntax können Sie Folgendes verwenden:
quelle
All dies führt intern zu einer aufgerufenen Methode
InternalGetValueAsString
. Der Unterschied zwischenToString
undGetName
wäre, dassGetName
zuerst einige Dinge überprüft werden müssen:GetType
den Wert, um dies zu überprüfen..ToString
Sie 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.ToString
Methode nicht dieselben Überprüfungsprobleme aufweist Als statische Methode würde ich schließen, dass dies.ToString
der schnellste Weg ist, um den Wert als Zeichenfolge zu erhalten.quelle
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 ,
quelle
Enum.GetName()
Format()
ist wirklich nur ein WrapperGetName()
mit einigen Formatierungsfunktionen (oderInternalGetValueAsString()
um genau zu sein).ToString()
ist so ziemlich das gleiche wieFormat()
. Ich denke, esGetName()
ist die beste Option, da es völlig offensichtlich ist, was es für jeden tut, der die Quelle liest.quelle
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.
quelle
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.
GetName
funktioniert, erfordert aber viel mehr Tastenanschläge.ToString()
scheint den Job sehr gut zu machen.quelle
Für VB-Liebhaber:
quelle
Das würde auch funktionieren.
quelle
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
Vergleich mit einer Aufzählung von 100 Elementen und 1000000 Iterationen:
quelle
Einfach: Namen in eine Liste auflisten:
quelle