A non-generic implementation of the static class Enums. When the type is known at compile-time the Enums class should be used instead, to provide type safety and to avoid boxing.
        /// <summary>
        /// Indicates whether <paramref name="value"/> is a valid flag combination of <paramref name="enumType"/>'s defined flags.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="value">The flags enum value.</param>
        /// <returns>Indication of whether <paramref name="value"/> is a valid flag combination of <paramref name="enumType"/>'s defined flags.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/> or <paramref name="value"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="value"/> is of an invalid type.</exception>
        public static bool IsValidFlagCombination(Type enumType, object value)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            if (value == null && info.IsNullable)
            {
                return(true);
            }

            return(info.EnumInfo.IsValidFlagCombination(value));
        }
        /// <summary>
        /// Indicates if <paramref name="value"/> has all of the flags that are defined in <paramref name="enumType"/>.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="value">The flags enum value.</param>
        /// <returns>Indication if <paramref name="value"/> has all of the flags that are defined in <paramref name="enumType"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/> or <paramref name="value"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="value"/> is of an invalid type.</exception>
        public static bool HasAllFlags(Type enumType, object value)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            if (value == null && info.IsNullable)
            {
                return(false);
            }

            return(info.EnumInfo.HasAllFlags(value));
        }
        /// <summary>
        /// Converts the string representation of one or more members or values of <paramref name="enumType"/> delimited with <paramref name="delimiter"/> to its respective value of type <paramref name="enumType"/>
        /// using the specified parsing enum formats. The parameter <paramref name="ignoreCase"/> specifies if the operation is case-insensitive.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="value">The enum members or values' string representation.</param>
        /// <param name="ignoreCase">Indicates if the operation is case-insensitive.</param>
        /// <param name="delimiter">The delimiter used to separate individual flags.</param>
        /// <param name="formats">The parsing enum formats.</param>
        /// <returns>The <paramref name="enumType"/> value that is represented by <paramref name="value"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/> or <paramref name="value"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="value"/> doesn't represent a member or value of <paramref name="enumType"/>
        /// -or-
        /// <paramref name="formats"/> contains an invalid value.</exception>
        /// <exception cref="OverflowException"><paramref name="value"/> is outside the range of the underlying type of <paramref name="enumType"/>.</exception>
        public static object ParseFlags(Type enumType, string value, bool ignoreCase, string delimiter, params EnumFormat[] formats)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            if (string.IsNullOrEmpty(value) && info.IsNullable)
            {
                return(null);
            }

            return(info.EnumInfo.ParseFlags(value, ignoreCase, delimiter, formats));
        }
        /// <summary>
        /// Retrieves the <see cref="EnumMember{TEnum}"/>s of the flags that compose <paramref name="value"/>.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="value">The flags enum value.</param>
        /// <returns>The <see cref="EnumMember{TEnum}"/>s of the flags that compose <paramref name="value"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/> or <paramref name="value"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="value"/> is of an invalid type.</exception>
        public static IEnumerable <EnumMember> GetFlagMembers(Type enumType, object value)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            if (value == null && info.IsNullable)
            {
                return(new EnumMember[0]);
            }

            return(info.EnumInfo.GetFlagMembers(value));
        }
        /// <summary>
        /// Retrieves <paramref name="value"/>'s flags formatted with <paramref name="formats"/> and delimited with <paramref name="delimiter"/>
        /// or if empty returns the zero flag formatted with <paramref name="formats"/>.
        /// If <paramref name="value"/> is not a valid flag combination <c>null</c> is returned.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="value">The flags enum value.</param>
        /// <param name="delimiter">The delimiter to use to separate individual flags.</param>
        /// <param name="formats">The output formats to use.</param>
        /// <returns><paramref name="value"/>'s flags formatted with <paramref name="formats"/> and delimited with <paramref name="delimiter"/>
        /// or if empty returns the zero flag formatted with <paramref name="formats"/>.
        /// If <paramref name="value"/> is not a valid flag combination <c>null</c> is returned.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/> or <paramref name="value"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="value"/> is of an invalid type
        /// -or-
        /// <paramref name="formats"/> contains an invalid value.</exception>
        public static string FormatFlags(Type enumType, object value, string delimiter, params EnumFormat[] formats)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            if (value == null && info.IsNullable)
            {
                return(null);
            }

            return(info.EnumInfo.FormatFlags(value, delimiter, formats));
        }
        private static bool TryParseFlags(Type enumType, string?value, bool ignoreCase, string?delimiter, out object?result, ValueCollection <EnumFormat> formats)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            if (info.IsNullable && string.IsNullOrEmpty(value))
            {
                result = null;
                return(true);
            }

            return(info.EnumCache.TryParseFlags(value, ignoreCase, delimiter, out result, formats));
        }
        /// <summary>
        /// Returns <paramref name="value"/> with all of it's flags toggled. Equivalent to the bitwise "xor" operator with <see cref="GetAllFlags(Type)"/>.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="value">The flags enum value.</param>
        /// <returns><paramref name="value"/> with all of it's flags toggled.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/> or <paramref name="value"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="value"/> is of an invalid type.</exception>
        public static object ToggleFlags(Type enumType, object value)
        {
            var info     = NonGenericEnums.GetNonGenericEnumInfo(enumType);
            var enumInfo = info.EnumInfo;

            if (value == null && info.IsNullable)
            {
                return(enumInfo.AllFlags);
            }

            return(enumInfo.ToggleFlags(value));
        }
        private static object?ParseFlags(Type enumType, string?value, bool ignoreCase, string?delimiter, ValueCollection <EnumFormat> formats)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            if (info.IsNullable && string.IsNullOrEmpty(value))
            {
                return(null);
            }

            Preconditions.NotNull(value, nameof(value));

            return(info.EnumCache.ParseFlags(value !, ignoreCase, delimiter, formats));
        }
        public static object CombineFlags(Type enumType, object?value, object?otherFlags)
        {
            var info  = NonGenericEnums.GetNonGenericEnumInfo(enumType);
            var cache = info.EnumCache;

            if (info.IsNullable)
            {
                if (value == null)
                {
                    return(otherFlags == null?cache.CombineFlags(null, true) : cache.ToObject(otherFlags, EnumValidation.None));
                }
                if (otherFlags == null)
                {
                    return(cache.ToObject(value, EnumValidation.None));
                }
            }

            return(cache.CombineFlags(value !, otherFlags !));
        }
        /// <summary>
        /// Combines the flags of <paramref name="value"/> and <paramref name="otherFlags"/>. Equivalent to the bitwise "or" operation.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="value">The flags enum value.</param>
        /// <param name="otherFlags">The other flags enum value.</param>
        /// <returns>Combination of <paramref name="value"/> with the flags in <paramref name="otherFlags"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/>, <paramref name="value"/>, or <paramref name="otherFlags"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="value"/> or <paramref name="otherFlags"/> is of an invalid type.</exception>
        public static object CombineFlags(Type enumType, object value, object otherFlags)
        {
            var info     = NonGenericEnums.GetNonGenericEnumInfo(enumType);
            var enumInfo = info.EnumInfo;

            if (info.IsNullable)
            {
                if (value == null)
                {
                    return(enumInfo.ToObject(otherFlags));
                }
                if (otherFlags == null)
                {
                    return(enumInfo.ToObject(value));
                }
            }

            return(enumInfo.CombineFlags(value, otherFlags));
        }
        public static bool HasAllFlags(Type enumType, object?value, object?otherFlags)
        {
            var info  = NonGenericEnums.GetNonGenericEnumInfo(enumType);
            var cache = info.EnumCache;

            if (info.IsNullable)
            {
                if (value == null)
                {
                    return(otherFlags == null || !cache.HasAnyFlags(otherFlags));
                }
                if (otherFlags == null)
                {
                    cache.ToObject(value, EnumValidation.None);
                    return(true);
                }
            }

            return(cache.HasAllFlags(value !, otherFlags !));
        }
        /// <summary>
        /// Indicates if <paramref name="value"/> has all of the flags that are in <paramref name="otherFlags"/>.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="value">The flags enum value.</param>
        /// <param name="otherFlags">The other flags enum value.</param>
        /// <returns>Indication if <paramref name="value"/> has all of the flags that are in <paramref name="otherFlags"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/>, <paramref name="value"/>, or <paramref name="otherFlags"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="value"/> or <paramref name="otherFlags"/> is of an invalid type.</exception>
        public static bool HasAllFlags(Type enumType, object value, object otherFlags)
        {
            var info     = NonGenericEnums.GetNonGenericEnumInfo(enumType);
            var enumInfo = info.EnumInfo;

            if (info.IsNullable)
            {
                if (value == null)
                {
                    return(!enumInfo.HasAnyFlags(otherFlags));
                }
                if (otherFlags == null)
                {
                    enumInfo.ToObject(value);
                    return(true);
                }
            }

            return(enumInfo.HasAllFlags(value, otherFlags));
        }
        public static int GetFlagCount(Type enumType, object?value, object?otherFlags)
        {
            var info  = NonGenericEnums.GetNonGenericEnumInfo(enumType);
            var cache = info.EnumCache;

            if (info.IsNullable)
            {
                if (value == null)
                {
                    if (otherFlags != null)
                    {
                        cache.ToObject(otherFlags, EnumValidation.None);
                    }
                    return(0);
                }
                if (otherFlags == null)
                {
                    cache.ToObject(value, EnumValidation.None);
                    return(0);
                }
            }

            return(cache.GetFlagCount(value !, otherFlags !));
        }
        private static string?FormatFlags(Type enumType, object?value, string?delimiter, ValueCollection <EnumFormat> formats)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            return(value == null && info.IsNullable ? null : info.EnumCache.FormatFlags(value !, delimiter, formats));
        }
        public static IEnumerable <EnumMember> GetFlagMembers(Type enumType, object?value)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            return(value == null && info.IsNullable ? ArrayHelper.Empty <EnumMember>() : info.EnumCache.GetFlagMembers(value !));
        }
 public static object GetAllFlags(Type enumType) => NonGenericEnums.GetCache(enumType).GetAllFlags();
        public static bool IsValidFlagCombination(Type enumType, object?value)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            return(value == null && info.IsNullable ? true : info.EnumCache.IsValidFlagCombination(value !));
        }
 public static bool IsFlagEnum(Type enumType) => NonGenericEnums.GetCache(enumType).IsFlagEnum;
        /// <summary>
        /// Combines all of the flags of <paramref name="flags"/>.
        /// </summary>
        /// <param name="enumType">The enum type.</param>
        /// <param name="flags">The flags enum values.</param>
        /// <returns>Combination of all of the flags of <paramref name="flags"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="enumType"/> or <paramref name="flags"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type
        /// -or-
        /// <paramref name="flags"/> contains a value that is of an invalid type.</exception>
        public static object CombineFlags(Type enumType, IEnumerable <object> flags)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            return(info.EnumInfo.CombineFlags(info.IsNullable ? flags?.Where(flag => flag != null) : flags));
        }
        public static object CombineFlags(Type enumType, IEnumerable <object?>?flags)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            return(info.EnumCache.CombineFlags(flags, info.IsNullable));
        }
 /// <summary>
 /// Retrieves all the flags defined by <paramref name="enumType"/>.
 /// </summary>
 /// <param name="enumType">The enum type.</param>
 /// <returns>All the flags defined by <paramref name="enumType"/>.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="enumType"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type.</exception>
 public static object GetAllFlags(Type enumType) => NonGenericEnums.GetInfo(enumType).AllFlags;
 /// <summary>
 /// The <see cref="NonGenericEnumComparer"/> constructor.
 /// </summary>
 /// <param name="enumType">The enum type.</param>
 /// <exception cref="ArgumentNullException"><paramref name="enumType"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentException"><paramref name="enumType"/> is not an enum type.</exception>
 public NonGenericEnumComparer(Type enumType)
 {
     _info = NonGenericEnums.GetNonGenericEnumInfo(enumType);
 }
        public static object ToggleFlags(Type enumType, object?value)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            return(value == null && info.IsNullable ? info.EnumCache.GetAllFlags() : info.EnumCache.ToggleFlags(value !));
        }
 /// <summary>
 /// Compares <paramref name="x"/> to <paramref name="y"/>.
 /// </summary>
 /// <param name="x">The first enum value.</param>
 /// <param name="y">The second enum value.</param>
 /// <returns>1 if <paramref name="x"/> is greater than <paramref name="y"/>, 0 if <paramref name="x"/> equals <paramref name="y"/>,
 /// and -1 if <paramref name="x"/> is less than <paramref name="y"/>.</returns>
 public int Compare(object x, object y) => NonGenericEnums.CompareToInternal(_info, x, y);
 /// <summary>
 /// Indicates if <paramref name="x"/> equals <paramref name="y"/>.
 /// </summary>
 /// <param name="x">The first enum value.</param>
 /// <param name="y">The second enum value.</param>
 /// <returns>Indication if <paramref name="x"/> equals <paramref name="y"/>.</returns>
 public new bool Equals(object x, object y) => NonGenericEnums.EqualsInternal(_info, x, y);
 public static int GetFlagCount(Type enumType) => NonGenericEnums.GetCache(enumType).GetFlagCount(enumType);
        public static int GetFlagCount(Type enumType, object?value)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            return(value == null && info.IsNullable ? 0 : info.EnumCache.GetFlagCount(value !));
        }
        public static bool HasAllFlags(Type enumType, object?value)
        {
            var info = NonGenericEnums.GetNonGenericEnumInfo(enumType);

            return(value == null && info.IsNullable ? false : info.EnumCache.HasAllFlags(value !));
        }