EnumUtils.cs 1.5 KB

12345678910111213141516171819202122232425262728293031323334
  1. using System.Collections.Concurrent;
  2. using System.Globalization;
  3. namespace MeloongCore;
  4. public static class EnumUtils {
  5. /// <summary>
  6. /// 获取枚举的所有值。
  7. /// </summary>
  8. private static IEnumerable<T> GetAllValues<T>() where T : struct, Enum
  9. => Enum.GetValues(typeof(T)).Cast<T>();
  10. /// <summary>
  11. /// 对于具有 <see cref="FlagsAttribute"/> 的枚举,返回其所有 Flag 值。
  12. /// 建议仅对没有极端值的正数枚举使用。
  13. /// </summary>
  14. /// <remarks>
  15. /// 会跳过:0、非 2 的幂的值、不在枚举值中的数、组合值、对应同一个枚举项的多个别名。
  16. /// </remarks>
  17. public static List<T> GetAllFlags<T>() where T : struct, Enum {
  18. if (allFlagsCache.TryGetValue(typeof(T), out var cached)) return cached.Cast<T>().ToList();
  19. if (!typeof(T).IsDefined(typeof(FlagsAttribute), inherit: false)) throw new ArgumentException($"枚举 {typeof(T).FullName} 没有定义 FlagsAttribute。");
  20. var flags = new List<T>();
  21. foreach (var element in EnumUtils.GetAllValues<T>().Distinct()) {
  22. var number = Convert.ToInt64(element, CultureInfo.InvariantCulture);
  23. if (number == 0 || (number & (number - 1)) != 0) continue; // 跳过 0 和非 2 的幂的值
  24. flags.Add(element);
  25. }
  26. allFlagsCache[typeof(T)] = flags.Cast<Enum>().ToList();
  27. return flags;
  28. }
  29. private static readonly ConcurrentDictionary<Type, List<Enum>> allFlagsCache = new();
  30. }