using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Extensions { public abstract class SmartEnum where TEnum : SmartEnum { private static readonly List _list = new(); // Despite analysis tool warnings, we want this static bool to be on this generic type (so that each TEnum has its own bool). private static bool _invoked; public static List List { get { if (!_invoked) { _invoked = true; // Force invocaiton/initialization by calling one of the derived members. typeof(TEnum).GetProperties(BindingFlags.Public | BindingFlags.Static) .FirstOrDefault(p => p.PropertyType == typeof(TEnum))?.GetValue(null, null); } return _list; } } public string Name { get; } public TValue Value { get; } protected SmartEnum(string name, TValue value) { Name = name; Value = value; TEnum item = this as TEnum; List.Add(item); } public static TEnum FromName(string name) { return List.Single(item => string.Equals(item.Name, name, StringComparison.OrdinalIgnoreCase)); } public static TEnum FromValue(TValue value) { // Can't use == to compare generics unless we constrain TValue to "class", which we don't want because then we couldn't use int. return List.Single(item => EqualityComparer.Default.Equals(item.Value, value)); } public override string ToString() => $"{Name} ({Value})"; public static implicit operator TValue(SmartEnum key) => key.Value; } }