Performans önemlidir
Daha iyi performans istiyorsanız, bu yol:
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");
}
}
}
Bunun performansı neden daha iyi?
Çünkü yerleşik yöntemlerin hepsi buna çok benzer kod kullanırlar , ancak umursadığımız bir sürü başka kod çalıştırırlar . C # Enum kodu genel olarak oldukça korkunç.
Yukarıdaki kod Linq-ified ve aerodinamik hale getirilmiştir, bu yüzden sadece önem verdiğimiz bitleri içerir.
Dahili kod neden yavaş?
Enum.ToString () -vs- Enum.GetName (..) ile ilgili ilk
Daima ikincisini kullanın. (Ya da daha iyisi, aşağıda da anlaşılacağı gibi).
ToString (), ikincisini dahili olarak kullanır, ancak yine, istemediğimiz bir sürü başka şey de yapar, örneğin bayrakları birleştirmeye, sayıları yazdırmaya çalışır vb.
Enum.GetName sırayla tüm alanları alır, tüm adlar için bir dize dizisi oluşturur, tüm ToCIntant64 değerlerini tüm RawConstantValues değerinde kullanır ve tüm değerlerin bir UInt64 dizisini oluşturur, her iki diziyi de UInt64 değerine göre sıralar ve son olarak UInt64 dizisinde bir BinarySearch yaparak istediğimiz değerin dizinini bulmak için name-array.
... sonra alanları atıyoruz ve sıralı diziler, alanı yeniden bulmak için bu ismi kullanıyor.
Tek kelime: "Ah!"