Leistung zählt
Wenn Sie eine bessere Leistung wünschen, ist dies der richtige Weg:
public static class AdvancedEnumExtensions
{
/// <summary>
/// Gets the custom attribute <typeparamref name="T"/> for the enum constant, if such a constant is defined and has such an attribute; otherwise null.
/// </summary>
public static T GetCustomAttribute<T>(this Enum value) where T : Attribute
{
return GetField(value)?.GetCustomAttribute<T>(inherit: false);
}
/// <summary>
/// Gets the FieldInfo for the enum constant, if such a constant is defined; otherwise null.
/// </summary>
public static FieldInfo GetField(this Enum value)
{
ulong u64 = ToUInt64(value);
return value
.GetType()
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
.Where(f => ToUInt64(f.GetRawConstantValue()) == u64)
.FirstOrDefault();
}
/// <summary>
/// Checks if an enum constant is defined for this enum value
/// </summary>
public static bool IsDefined(this Enum value)
{
return GetField(value) != null;
}
/// <summary>
/// Converts the enum value to UInt64
/// </summary>
public static ulong ToUInt64(this Enum value) => ToUInt64((object)value);
private static ulong ToUInt64(object value)
{
switch (Convert.GetTypeCode(value))
{
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
return unchecked((ulong)Convert.ToInt64(value, CultureInfo.InvariantCulture));
case TypeCode.Byte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Char:
case TypeCode.Boolean:
return Convert.ToUInt64(value, CultureInfo.InvariantCulture);
default: throw new InvalidOperationException("UnknownEnumType");
}
}
}
Warum ist die Leistung so besser?
Denn die eingebauten Methoden verwenden alle einen ähnlichen Code, außer sie führen auch einen Haufen anderen Code aus, der uns nicht interessiert . Der Enum-Code von C# ist im Allgemeinen ziemlich schrecklich.
Der obige Code wurde in Linq umgewandelt und gestrafft, so dass er nur die für uns wichtigen Teile enthält.
Warum ist der integrierte Code langsam?
Zunächst zu Enum.ToString() -vs- Enum.GetName(..)
Verwenden Sie immer Letzteres. (Oder besser keine, wie weiter unten deutlich wird.)
ToString() verwendet letzteres intern, macht aber auch wieder eine Menge anderer Dinge, die wir nicht wollen, z.B. versucht, Flags zu kombinieren, Zahlen auszugeben usw. Wir sind nur an den Konstanten interessiert, die innerhalb der Enum definiert sind.
Enum.GetName holt wiederum alle Felder ab, erstellt ein String-Array für alle Namen, verwendet das obige ToUInt64 auf alle RawConstantValues, um ein UInt64-Array mit allen Werten zu erstellen, sortiert beide Arrays nach dem UInt64-Wert und holt schließlich den Namen aus dem Name-Array, indem es eine BinarySearch im UInt64-Array durchführt, um den Index des gewünschten Wertes zu finden.
...und dann werfen wir die Felder und die sortierten Arrays weg und verwenden diesen Namen, um das Feld wieder zu finden.
Ein Wort: "Igitt!"
0 Stimmen
Aus einer anderen Frage stackoverflow.com/questions/469287/
0 Stimmen
Mögliche Duplikate von Kennt jemand eine schnelle Möglichkeit, um benutzerdefinierte Attribute auf einen Enum-Wert zu erhalten?
3 Stimmen
Der für die Beschreibung erforderliche Namespace ist System.ComponentModel
0 Stimmen
Sie können auch einfach System.ComponentModel nicht verwenden und einfach Ihren eigenen Attributtyp verwenden; es gibt wirklich nichts Besonderes an
DescriptionAttribute
.0 Stimmen
Bitte sehen Sie sich diesen Link an: stackoverflow.com/a/58954215/5576498