// TEnumX must either be the System.Enum class or an EnumCompatible primitive type (the latter of which includes user defined System.Enums). internal virtual bool TryGetEnumValueInternal <TEnumX>(out TEnumX enumValue, bool allowConversion) where TEnumX : IConvertible { AZAssert.Internal(Meta.Evaluate.IsEnumCompatible <TEnumX>(), "not enum compatible"); enumValue = default(TEnumX); return(false); }
internal bool TryInitializeName(string name) { AZAssert.NotEmptyInternal(name, nameof(name)); if (Name == null) { Name = name; return(true); } return(false); }
/// <summary> /// Tries to retrieve the System.Enum value paired to this Enumeration value. /// </summary><returns> /// The System.Enum value paired to this Enumeration value; /// or null if this Enumeration value isn't paired to any System.Enum value. /// </returns> public System.Enum TryGetEnumValue() { if (!HasEnumValueImpl) { return(null); } System.Enum enumValue; TryGetEnumValueInternal(out enumValue, false); AZAssert.Internal(enumValue != null, "failed to get enum value that should exists"); return(enumValue); }
private static bool ValueExists(TEnumeration[] values, TEnum value, int count, EqualityComparer <TEnum> eq) { AZAssert.NotNullInternal(values, nameof(values)); AZAssert.NotNullInternal(eq, nameof(eq)); AZAssert.BoundsInternal(values, count, nameof(count), true); for (int i = 0; i < count; ++i) { if (eq.Equals(values[i].EnumValue, value)) { return(true); } } return(false); }
// lastVal is the instance that is calling InitializeNames (from its ctor). (lastVal == values[values.Length - 1]) private static void InitializeInfoAndNames(TEnumeration lastVal) { AZAssert.NotNullInternal(lastVal, nameof(lastVal)); AZAssert.NotNullInternal(fields, nameof(fields)); string err = null; var t = typeof(TEnumeration); FieldInfo[] fieldArray = fields; for (int i = 0; i < fieldArray.Length; ++i) { var f = fieldArray[i]; if (!f.IsInitOnly || f.FieldType != t) { err = ErrPrefix + "." + f.Name + ERR_FIELD_TYPE; break; } var val = lastVal.GetStaticFieldValue(f); if (val == null) // we expect exactly one field to be null: the last field in textual order (i.e. the field that corresponds to the instance that is calling this method). { val = lastVal; // if this happens more than once it means that not all fields have initializers, but then TryInitializeName will fail below, so it will get caught. } if (!val.TryInitializeName(f.Name)) // TryInitializeName fails if name is already set, and since values.Length == fields.Length this ensures uniqueness! { err = ErrPrefix + "." + f.Name + ERR_FIELD_VALUE; break; } } if (err != null) { Debug.Assert(false, err); throw new Exception(err); } fields = null; // fields array not needed anymore. ev_instance = new EnumValues <TEnumeration>(values); // info init. // late initialization completed successfully. }
// Enum.TryParse doesn't exist in .net 3.5 :( private static void InitializeEnumValues() { AZAssert.Internal(_IsInitialized, "names not initialized"); bool isOrdinalPaired = true; var eq = eqcTEnum; TEnumeration v = null; try { var tEnum = typeof(TEnum); var values = ValArrayInternal; for (int i = 0; i < values.Length; ++i) { v = values[i]; v.EnumValue = (TEnum)Enum.Parse(tEnum, v.Name); // Verify requirement: Enum value uniqueness if (ValueExists(values, v.EnumValue, i, eq)) { Debug.Assert(false, ErrPrefix + "." + v.Name + ERR_ENUM_UNIQUE); throw new Exception(ErrPrefix + "." + v.Name + ERR_ENUM_UNIQUE); } isOrdinalPaired &= (ulong)i == ToUInt64(v.EnumValue); // i == Ordinal } } catch (ArgumentException e) { Debug.Assert(false, ErrPrefix + v.Name + ERR_ENUM_MISSING, e.Message); throw new Exception(ErrPrefix + v.Name + ERR_ENUM_MISSING, e); } catch (Exception e) { throw new Exception(ErrPrefix + ERR_BASE, e); // This should never happen! } if (isOrdinalPaired) { eqcTEnum = null; } }
// TEnumX must either be System.Enum or a valueType. internal sealed override bool TryGetEnumValueInternal <TEnumX>(out TEnumX enumValue, bool allowConversion) // (TEnumX : IConvertible) { if (EnumValue is TEnumX) // the System.Enum case will fall in here: { enumValue = (TEnumX)(object)EnumValue; // not sure how to get around this ugly double-cast... System.Enum is a bastard! :( return(true); } else { AZAssert.Internal(Evaluate.IsEnumCompatible <TEnumX>(), "not enum compatible"); if (allowConversion) { // we *might* be able to perform some conversion magic even if the type is wrong ;) return(Numeric.TryConvertInteger(EnumValue, out enumValue)); } else { enumValue = default(TEnumX); return(false); } } }
// internal instantiation only! internal EnumValues(TEnumeration[] values) { AZAssert.NotNullInternal(values, nameof(values)); this.values = values; }