using System.Globalization;
namespace MeloongCore;
public static class EnumUtils {
///
/// 获取枚举的所有值。
///
private static IEnumerable GetAllValues() where T : struct, Enum
=> Enum.GetValues(typeof(T)).Cast();
///
/// 将字符串转换为枚举。
/// 支持枚举名或枚举序数;若为空字符串或 则返回 0。
/// 转换失败会抛出异常。
///
public static T FromString(string? value) where T : struct, Enum {
if (string.IsNullOrEmpty(value)) {
return (T) Enum.ToObject(typeof(T), 0);
} else if (double.TryParse(value, NumberStyles.Float, CultureInfo.CurrentCulture, out var number)) {
return (T) Enum.ToObject(typeof(T), Convert.ToInt64(number));
} else {
return (T) Enum.Parse(typeof(T), value, true);
}
}
public static bool HasFlagF(this T value, T flag) where T : struct, Enum
=> value.HasFlag(flag) && !EqualityComparer.Default.Equals(flag, default);
///
/// 对于具有 的枚举,返回其所有 Flag 值。
/// 建议仅对没有极端值的正数枚举使用。
///
///
/// 会跳过:0、非 2 的幂的值、不在枚举值中的数、组合值、对应同一个枚举项的多个别名。
///
public static List GetAllFlags() where T : struct, Enum {
if (allFlagsCache.TryGetValue(typeof(T), out var cached)) return cached.Cast().ToList();
if (!typeof(T).IsDefined(typeof(FlagsAttribute), inherit: false)) throw new ArgumentException($"枚举 {typeof(T).FullName} 没有定义 FlagsAttribute。");
var flags = new List();
foreach (var element in EnumUtils.GetAllValues().Distinct()) {
var number = Convert.ToInt64(element, CultureInfo.InvariantCulture);
if (number == 0 || (number & (number - 1)) != 0) continue; // 跳过 0 和非 2 的幂的值
flags.Add(element);
}
allFlagsCache[typeof(T)] = flags.Cast().ToList();
return flags;
}
private static readonly ConcurrentDictionary> allFlagsCache = new();
}