mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-14 12:15:05 +00:00
perf: Adding contrains for enum methods, faster HasFlag/s checks
This commit is contained in:
@@ -30,6 +30,7 @@ namespace ICD.Common.Utils
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsEnumType<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return IsEnumType(typeof(T));
|
||||
}
|
||||
@@ -55,9 +56,9 @@ namespace ICD.Common.Utils
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsEnum<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
return value != null && IsEnumType(value.GetType());
|
||||
return IsEnumType(value.GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,6 +68,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDefined<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnumType<T>())
|
||||
throw new InvalidOperationException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -94,6 +96,7 @@ namespace ICD.Common.Utils
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetValues<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
Type type = typeof(T);
|
||||
|
||||
@@ -122,6 +125,7 @@ namespace ICD.Common.Utils
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> GetValuesUncached<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return GetValuesUncached(typeof(T)).Cast<T>();
|
||||
}
|
||||
@@ -151,6 +155,7 @@ namespace ICD.Common.Utils
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetValuesExceptNone<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return GetFlagsExceptNone<T>();
|
||||
}
|
||||
@@ -174,6 +179,7 @@ namespace ICD.Common.Utils
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static bool IsFlagsEnum<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return IsFlagsEnum(typeof(T));
|
||||
}
|
||||
@@ -198,6 +204,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetFlagsIntersection<T>(params T[] values)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (values.Length == 0)
|
||||
return default(T);
|
||||
@@ -217,6 +224,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetFlagsIntersection<T>(T a, T b)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
int aInt = (int)(object)a;
|
||||
int bInt = (int)(object)b;
|
||||
@@ -231,10 +239,10 @@ namespace ICD.Common.Utils
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetFlags<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnum(value))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value.GetType().Name), "value");
|
||||
|
||||
Type type = typeof(T);
|
||||
int valueInt = (int)(object)value;
|
||||
@@ -262,6 +270,7 @@ namespace ICD.Common.Utils
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetFlagsExceptNone<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -277,10 +286,10 @@ namespace ICD.Common.Utils
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetFlagsExceptNone<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnum(value))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value.GetType().Name), "value");
|
||||
|
||||
return GetFlags(value).Except(default(T));
|
||||
}
|
||||
@@ -295,10 +304,10 @@ namespace ICD.Common.Utils
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetAllFlagCombinationsExceptNone<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnum(value))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value.GetType().Name), "value");
|
||||
|
||||
int maxEnumValue = (GetValues<T>().Max(v => (int)(object)v) * 2) -1;
|
||||
return Enumerable.Range(1, maxEnumValue).Select(i => (T)(object)i ).Where(v => HasFlags(value, v));
|
||||
@@ -310,6 +319,7 @@ namespace ICD.Common.Utils
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static T GetFlagsAllValue<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -326,16 +336,15 @@ namespace ICD.Common.Utils
|
||||
/// <param name="flag"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasFlag<T>(T value, T flag)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnum(value))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value.GetType().Name), "value");
|
||||
|
||||
if (!IsEnum(flag))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", flag == null ? "NULL" : flag.GetType().Name), "flag");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", flag.GetType().Name), "flag");
|
||||
|
||||
return ToEnum(value).HasFlag(ToEnum(flag));
|
||||
return HasFlags(value, flag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -346,16 +355,18 @@ namespace ICD.Common.Utils
|
||||
/// <param name="flags"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasFlags<T>(T value, T flags)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnum(value))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value.GetType().Name), "value");
|
||||
|
||||
if (!IsEnum(flags))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", flags == null ? "NULL" : flags.GetType().Name), "flags");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", flags.GetType().Name), "flags");
|
||||
|
||||
return ToEnum(value).HasFlags(ToEnum(flags));
|
||||
int a = (int)(object)value;
|
||||
int b = (int)(object)flags;
|
||||
|
||||
return (a & b) == b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -365,10 +376,10 @@ namespace ICD.Common.Utils
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasSingleFlag<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnum(value))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value.GetType().Name), "value");
|
||||
|
||||
return HasAnyFlags(value) && !HasMultipleFlags(value);
|
||||
}
|
||||
@@ -379,10 +390,10 @@ namespace ICD.Common.Utils
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasMultipleFlags<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnum(value))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value");
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value.GetType().Name), "value");
|
||||
|
||||
return HasMultipleFlags((int)(object)value);
|
||||
}
|
||||
@@ -405,6 +416,7 @@ namespace ICD.Common.Utils
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool HasAnyFlags<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return HasAnyFlags((int)(object)value);
|
||||
}
|
||||
@@ -428,6 +440,7 @@ namespace ICD.Common.Utils
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool HasAnyFlags<T>(T value, T other)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
T intersection = GetFlagsIntersection(value, other);
|
||||
return HasAnyFlags(intersection);
|
||||
@@ -445,6 +458,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="ignoreCase"></param>
|
||||
/// <returns></returns>
|
||||
public static T Parse<T>(string data, bool ignoreCase)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -466,6 +480,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParse<T>(string data, bool ignoreCase, out T result)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -492,6 +507,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="ignoreCase"></param>
|
||||
/// <returns></returns>
|
||||
public static T ParseStrict<T>(string data, bool ignoreCase)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -524,6 +540,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryParseStrict<T>(string data, bool ignoreCase, out T result)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -541,21 +558,6 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given enum value to an Enum.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static Enum ToEnum<T>(T value)
|
||||
{
|
||||
if (!IsEnum(value))
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value");
|
||||
|
||||
return (Enum)(object)value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,51 +12,49 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="value">Flag to check for</param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool HasFlag(this Enum extends, Enum value)
|
||||
public static bool HasFlag<T>(this T extends, T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
if (!EnumUtils.IsEnum(extends))
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", extends.GetType().Name), "extends");
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (!EnumUtils.IsEnum(value))
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", value.GetType().Name), "value");
|
||||
|
||||
if (EnumUtils.HasMultipleFlags(value))
|
||||
throw new ArgumentException("Value has multiple flags", "value");
|
||||
|
||||
return extends.HasFlags(value);
|
||||
return EnumUtils.HasFlag(extends, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check to see if a flags enumeration has all of the given flags set.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool HasFlags(this Enum extends, Enum value)
|
||||
public static bool HasFlags<T>(this T extends, T values)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
if (!EnumUtils.IsEnum(extends))
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", extends.GetType().Name), "extends");
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
if (!EnumUtils.IsEnum(values))
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", values.GetType().Name), "values");
|
||||
|
||||
// Not as good as the .NET 4 version of this function, but should be good enough
|
||||
if (extends.GetType() != value.GetType())
|
||||
{
|
||||
string message = string.Format("Enumeration type mismatch. The flag is of type '{0}', was expecting '{1}'.",
|
||||
value.GetType(), extends.GetType());
|
||||
throw new ArgumentException(message);
|
||||
}
|
||||
|
||||
int num = (int)(object)value;
|
||||
return ((int)(object)extends & num) == num;
|
||||
return EnumUtils.HasFlags(extends, values);
|
||||
}
|
||||
|
||||
public static ushort ToUShort(this Enum extends)
|
||||
/// <summary>
|
||||
/// Returns the enum value as a
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI("S+")]
|
||||
public static ushort ToUShort<T>(this T extends)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
if (!EnumUtils.IsEnum(extends))
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", extends.GetType().Name), "extends");
|
||||
|
||||
return (ushort)(object)extends;
|
||||
}
|
||||
|
||||
@@ -155,6 +155,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T GetValueAsEnum<T>(this JsonReader extends)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
@@ -392,6 +392,7 @@ namespace ICD.Common.Utils.Xml
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T ReadElementContentAsEnum<T>(this IcdXmlReader extends, bool ignoreCase)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
@@ -422,6 +422,7 @@ namespace ICD.Common.Utils.Xml
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T ReadChildElementContentAsEnum<T>(string xml, string childElement, bool ignoreCase)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!EnumUtils.IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -608,7 +609,7 @@ namespace ICD.Common.Utils.Xml
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T? TryReadChildElementContentAsEnum<T>(string xml, string childElement, bool ignoreCase)
|
||||
where T : struct
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!EnumUtils.IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -628,6 +629,7 @@ namespace ICD.Common.Utils.Xml
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool TryReadChildElementContentAsEnum<T>(string xml, string childElement, bool ignoreCase, out T output)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!EnumUtils.IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
@@ -731,6 +733,7 @@ namespace ICD.Common.Utils.Xml
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T ReadElementContentAsEnum<T>(string xml, bool ignoreCase)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (!EnumUtils.IsEnumType<T>())
|
||||
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||
|
||||
Reference in New Issue
Block a user