static Cache() { Type = typeof(T); UnderlyingType = Enum.GetUnderlyingType(Type); Values = (Enum.GetValues(Type) as T[]).AsReadOnly(); Names = Enum.GetNames(Type).Select(string.Intern).ToReadOnlyArray(); Members = Names.Select(x => new Member <T>(x)).ToReadOnlyArray(); MinValue = Values.DefaultIfEmpty().Min(); MaxValue = Values.DefaultIfEmpty().Max(); IsEmpty = Values.Count == 0; IsFlags = Attribute.IsDefined(Type, typeof(FlagsAttribute)); var distinctedMember = Members.OrderBy(x => x.Value).Distinct(new Member <T> .ValueComparer()).ToArray(); MemberByName = Members.ToFrozenStringKeyDictionary(x => x.Name); UnderlyingOperation = Type.GetTypeCode(Type) switch { TypeCode.SByte => SByteOperation <T> .Create(MinValue, MaxValue, distinctedMember), TypeCode.Byte => ByteOperation <T> .Create(MinValue, MaxValue, distinctedMember), TypeCode.Int16 => Int16Operation <T> .Create(MinValue, MaxValue, distinctedMember), TypeCode.UInt16 => UInt16Operation <T> .Create(MinValue, MaxValue, distinctedMember), TypeCode.Int32 => Int32Operation <T> .Create(MinValue, MaxValue, distinctedMember), TypeCode.UInt32 => UInt32Operation <T> .Create(MinValue, MaxValue, distinctedMember), TypeCode.Int64 => Int64Operation <T> .Create(MinValue, MaxValue, distinctedMember), TypeCode.UInt64 => UInt64Operation <T> .Create(MinValue, MaxValue, distinctedMember), _ => throw new InvalidOperationException(), }; }
static void Cache <T>() where T : struct, Enum { var type = typeof(T); var underlyingType = Enum.GetUnderlyingType(type); var values = ((T[])Enum.GetValues(type)).AsReadOnly(); var names = Enum.GetNames(type).ToReadOnlyArray(); var members = names.Select(x => new Member <T>(x)).ToReadOnlyArray(); var minValue = values.DefaultIfEmpty().Min(); var maxValue = values.DefaultIfEmpty().Max(); var isEmpty = values.Count == 0; var isFlags = Attribute.IsDefined(type, typeof(FlagsAttribute)); var distinctedMembers = members.Distinct(new Member <T> .ValueComparer()).ToArray(); var memberByValue = distinctedMembers.ToFrozenDictionary(x => x.Value); var memberByName = members.ToFrozenStringKeyDictionary(x => x.Name); var underlyingOperation = Type.GetTypeCode(type) switch { TypeCode.SByte => SByteOperation <T> .Create(minValue, maxValue, distinctedMembers), TypeCode.Byte => ByteOperation <T> .Create(minValue, maxValue, distinctedMembers), TypeCode.Int16 => Int16Operation <T> .Create(minValue, maxValue, distinctedMembers), TypeCode.UInt16 => UInt16Operation <T> .Create(minValue, maxValue, distinctedMembers), TypeCode.Int32 => Int32Operation <T> .Create(minValue, maxValue, distinctedMembers), TypeCode.UInt32 => UInt32Operation <T> .Create(minValue, maxValue, distinctedMembers), TypeCode.Int64 => Int64Operation <T> .Create(minValue, maxValue, distinctedMembers), TypeCode.UInt64 => UInt64Operation <T> .Create(minValue, maxValue, distinctedMembers), _ => throw new InvalidOperationException(), }; }
/// <summary> /// Returns an indication whether a constant with a specified value exists in a specified enumeration. /// </summary> /// <param name="value"></param> /// <typeparam name="T">Enum type</typeparam> /// <returns></returns> public static bool IsDefined <T>(sbyte value) where T : struct, Enum { if (Cache_UnderlyingOperation <T> .UnderlyingType == typeof(sbyte)) { return(SByteOperation <T> .IsDefined(ref value)); } throw new ArgumentException(IsDefinedTypeMismatchMessage); }
static Cache_UnderlyingOperation() { var type = Cache_Type <T> .Type; var min = Cache_MinMaxValues <T> .MinValue; var max = Cache_MinMaxValues <T> .MaxValue; var distincted = Cache_Members <T> .Members.OrderBy(x => x.Value).Distinct(new Member <T> .ValueComparer()).ToArray(); UnderlyingType = Cache_Type <T> .UnderlyingType; UnderlyingOperation = Type.GetTypeCode(type) switch { TypeCode.SByte => SByteOperation <T> .Create(min, max, distincted), TypeCode.Byte => ByteOperation <T> .Create(min, max, distincted), TypeCode.Int16 => Int16Operation <T> .Create(min, max, distincted), TypeCode.UInt16 => UInt16Operation <T> .Create(min, max, distincted), TypeCode.Int32 => Int32Operation <T> .Create(min, max, distincted), TypeCode.UInt32 => UInt32Operation <T> .Create(min, max, distincted), TypeCode.Int64 => Int64Operation <T> .Create(min, max, distincted), TypeCode.UInt64 => UInt64Operation <T> .Create(min, max, distincted), _ => throw new InvalidOperationException(), }; }
static CacheUnderlyingOperation() { Type type = CacheType <T> .Type; T min = CacheMinMaxValues <T> .MinValue; T max = CacheMinMaxValues <T> .MaxValue; EnumMember <T>[] distincted = CacheMembers <T> .Members.OrderBy(x => x.Value).Distinct(new EnumMember <T> .ValueComparer()).ToArray(); UnderlyingType = CacheType <T> .UnderlyingType; // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault UnderlyingOperation = Type.GetTypeCode(type) switch { TypeCode.SByte => SByteOperation <T> .Create(min, max, distincted), TypeCode.Byte => ByteOperation <T> .Create(min, max, distincted), TypeCode.Int16 => Int16Operation <T> .Create(min, max, distincted), TypeCode.UInt16 => UInt16Operation <T> .Create(min, max, distincted), TypeCode.Int32 => Int32Operation <T> .Create(min, max, distincted), TypeCode.UInt32 => UInt32Operation <T> .Create(min, max, distincted), TypeCode.Int64 => Int64Operation <T> .Create(min, max, distincted), TypeCode.UInt64 => UInt64Operation <T> .Create(min, max, distincted), _ => throw new InvalidOperationException() }; } }