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?
Welches ist die bevorzugte Methode zum Konvertieren einer Aufzählung in einen String in .NET 3.5?
Warum sollte ich eines davon den anderen vorziehen? Leistung man besser?
Antworten:
Ab C # 6 ist der neue nameof
Operator 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.
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üßten nameof(SomeEnum.FooBar)
bekommen "FooBar"
.
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);
}
In meinen Tests Enum.GetName
war schneller und mit ordentlichem Abstand. Interne ToString
Anrufe 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, ToString
da es einen viel saubereren Anruf bietet. Kontrast
Enum.GetName(typeof(Bla), value)
mit
value.ToString()
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)
All dies führt intern zu einer aufgerufenen Methode InternalGetValueAsString
. Der Unterschied zwischen ToString
und GetName
wäre, dass GetName
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.
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 verwendenenum.ToString()
,enum.GetNames()
,enum.GetName()
,enum.Format()
oderenum.Parse()
eine ENUM in eine Zeichenfolge zu konvertieren. Verwenden Sie stattdessen eine switch-Anweisung und internationalisieren Sie die Namen bei Bedarf.
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.
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. GetName
funktioniert, 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