/// <summary> /// Decrements an enum to the previous available value. /// NOTE: Throws an exception if a combined enum is passed. Check isFlaggedType and DoesMaskHaveMultiple first. /// </summary> /// <exception cref="ArgumentException">Type mismatch between enumValue and T.</exception> /// <exception cref="ArgumentException">Passed enumValue cannot be a combined enum.</exception> /// <exception cref="ArgumentOutOfRangeException">"Passed enumValue decremented beyond its range.</exception> /// <typeparam name="T"></typeparam> /// <param name="enumValue">The enum to use.</param> /// <param name="loopAround">Should a value decremented beyond its bounds loop around? If false, throws an ArgumentOutOfRangeException if bounds are exceeded.</param> /// <returns></returns> public static T Decrement <T>(Enum enumValue, bool loopAround = true) where T : struct, IConvertible { if (enumValue.GetType() != typeof(T)) { throw new ArgumentException("Type mismatch between enumValue \"" + enumValue.GetType() + "\" and T \"" + typeof(T) + "\"."); } if (isFlaggedType <T>() && DoesMaskHaveMultiple(enumValue)) { throw new ArgumentException("Passed enumValue \"" + enumValue.ToString() + "\" cannot be a combined enum."); } List <int> values = GetValuesInternal(enumValue.GetType()); int index = values.IndexOf((int)(object)enumValue); if (index > 0) { return(CastTo <T> .From <int>(values[index - 1])); } else if (loopAround) { return(CastTo <T> .From <int>(values[values.Count - 1])); } throw new ArgumentOutOfRangeException("enumValue", "Passed enumValue \"" + enumValue.ToString() + "\" decremented beyond its range."); }
/// <summary> /// Returns an enum mask that contains all the entry values (casts ~0). /// </summary> /// <exception cref="ArgumentException">Passed T is not an enum.</exception> /// <typeparam name="T"></typeparam> /// <returns></returns> public static T All <T>() where T : struct, IConvertible { if (!typeof(T).IsEnum) { throw new ArgumentException("Passed T \"" + typeof(T) + "\" is not an enum or int."); } return(CastTo <T> .From <int>(~0)); }
/// <summary> /// Determines if there are any overlaps between two enums (works for both being bitmasked flag enums). /// </summary> /// <exception cref="ArgumentException">Passed T is not an enum or int.</exception> /// <typeparam name="T">Either an enum or int.</typeparam> /// <param name="enum1">Enum to check containing within.</param> /// <param name="enum2"></param> /// <returns></returns> public static bool ContainsAny <T>(this T enum1, T enum2) where T : struct, IConvertible { if (!typeof(T).IsEnum && typeof(T) != typeof(int)) { throw new ArgumentException("Passed T \"" + typeof(T) + "\" is not an enum or int."); } return((CastTo <int> .From <T>(enum1) & CastTo <int> .From <T>(enum2)) != 0); }
/// <summary> /// Creates a mask that contains only the layers not shared between two masks. /// NOTE: Is not the same as Remove! /// </summary> /// <exception cref="ArgumentException">Type mismatch between enumValue and T.</exception> /// <typeparam name="T"></typeparam> /// <param name="enumValue"></param> /// <param name="flag"></param> public static T Difference <T>(this Enum enumValue, T flag) where T : struct, IConvertible { if (enumValue.GetType() != typeof(T)) { throw new ArgumentException("Type mismatch between enumValue \"" + enumValue.GetType() + "\" and T \"" + typeof(T) + "\"."); } return(CastTo <T> .From <int>((int)(object)enumValue ^ CastTo <int> .From <T>(flag))); }
/// <summary> /// Returns true if a bitmasked enum contains another enum (or int). /// Mimics the 4.0 HasFlag method. /// </summary> /// <exception cref="ArgumentException">Passed T is not an enum or int.</exception> /// <typeparam name="T">Either an enum or int.</typeparam> /// <param name="total">Enum to check containing within.</param> /// <param name="value">Enum to check if contained within Total. Can also be a bitmasked enum.</param> /// <returns>bool; If enum or int, returns if the Total contains the Value. Otherwise, returns false.</returns> public static bool Contains <T>(this T total, T value) where T : struct, IConvertible { if (!typeof(T).IsEnum && typeof(T) != typeof(int)) { throw new ArgumentException("Passed T \"" + typeof(T) + "\" is not an enum or int."); } int valueInt = CastTo <int> .From <T>(value); return((valueInt & CastTo <int> .From <T>(total)) == valueInt); }