เรื่องประสิทธิภาพ
หากคุณต้องการประสิทธิภาพที่ดีขึ้นนี่คือวิธีที่จะไป:
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");
}
}
}
ทำไมจึงมีประสิทธิภาพดีกว่า
เนื่องจากวิธีการในตัวทุกคนใช้รหัสที่คล้ายกันมากยกเว้นพวกเขาจะเรียกใช้รหัสอื่น ๆ ที่เราไม่สนใจที่เราไม่สนใจเกี่ยวกับ รหัส Enum ของ C # นั้นค่อนข้างน่ากลัวโดยทั่วไป
โค้ดข้างต้นได้รับ Linq-ified และคล่องตัวดังนั้นจึงมีเพียงบิตที่เราสนใจ
ทำไมรหัสในตัวจึงช้า
อันดับแรกเกี่ยวกับ Enum.ToString () -vs- Enum.GetName (.. )
ใช้หลังเสมอ (หรือดีกว่ายังไม่มีตามที่จะชัดเจนด้านล่าง)
ToString () ใช้สิ่งที่อยู่ภายใน แต่อีกครั้งยังทำสิ่งอื่น ๆ ที่เราไม่ต้องการเช่นพยายามรวมแฟล็กพิมพ์ตัวเลข ฯลฯ เราสนใจเฉพาะค่าคงที่ที่กำหนดไว้ใน enum
Enum.GetName รับค่าเขตข้อมูลทั้งหมดสร้างอาร์เรย์สตริงสำหรับชื่อทั้งหมดใช้ ToUInt64 ด้านบนของ RawConstantValues ทั้งหมดเพื่อสร้างอาร์เรย์ UInt64 ของค่าทั้งหมดเรียงลำดับอาร์เรย์ทั้งสองตามค่า UInt64 และสุดท้ายได้รับชื่อจาก ชื่ออาร์เรย์ด้วยการทำ BinarySearch ในอาร์เรย์ UInt64 เพื่อค้นหาดัชนีของค่าที่เราต้องการ
... จากนั้นเราก็โยนฟิลด์และอาร์เรย์ที่เรียงแล้วออกไปใช้ชื่อนั้นเพื่อค้นหาฟิลด์อีกครั้ง
หนึ่งคำ: "ฮึ!"