La performance compte
Si vous voulez de meilleures performances, voici la voie à suivre:
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");
}
}
}
Pourquoi cela a-t-il de meilleures performances?
Parce que les méthodes intégrées utilisent toutes du code très similaire à ceci, sauf qu'elles exécutent également un tas d'autres codes dont nous ne nous soucions pas . Le code Enum de C # est assez horrible en général.
Le code ci-dessus a été Linq-ified et rationalisé afin qu'il ne contienne que les bits qui nous intéressent.
Pourquoi le code intégré est-il lent?
Premièrement concernant Enum.ToString () -vs- Enum.GetName (..)
Utilisez toujours ce dernier. (Ou mieux encore ni l'un ni l'autre, comme cela apparaîtra clairement ci-dessous.)
ToString () utilise ce dernier en interne, mais encore une fois, fait un tas d'autres choses que nous ne voulons pas, par exemple, essaie de combiner des drapeaux, d'imprimer des nombres, etc. Nous ne sommes intéressés que par les constantes définies à l'intérieur de l'énumération.
Enum.GetName obtient à son tour tous les champs, crée un tableau de chaînes pour tous les noms, utilise le ToUInt64 ci-dessus sur tous leurs RawConstantValues pour créer un tableau UInt64 de toutes les valeurs, trie les deux tableaux en fonction de la valeur UInt64 et obtient enfin le nom de le tableau de noms en faisant une recherche binaire dans le tableau UInt64 pour trouver l'index de la valeur que nous voulions.
... puis nous jetons les champs et les tableaux triés utilisent ce nom pour retrouver le champ.
Un mot: "Ugh!"