From 591240d973df7aca6631386dcf2ef111ceec4274 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 25 Jul 2018 14:23:25 -0400 Subject: [PATCH] perf: Reducing boxing operations in enum utils --- ICD.Common.Utils.Tests/EnumUtilsTest.cs | 11 +----- ICD.Common.Utils/EnumUtils.cs | 52 +++++++++---------------- 2 files changed, 19 insertions(+), 44 deletions(-) diff --git a/ICD.Common.Utils.Tests/EnumUtilsTest.cs b/ICD.Common.Utils.Tests/EnumUtilsTest.cs index f1d84f1..15a965e 100644 --- a/ICD.Common.Utils.Tests/EnumUtilsTest.cs +++ b/ICD.Common.Utils.Tests/EnumUtilsTest.cs @@ -79,15 +79,6 @@ namespace ICD.Common.Utils.Tests #region Values - [Test] - public void GetUnderlyingValueTest() - { - Assert.AreEqual(0, EnumUtils.GetUnderlyingValue(eTestEnum.None)); - Assert.AreEqual(1, EnumUtils.GetUnderlyingValue(eTestEnum.A)); - Assert.AreEqual(2, EnumUtils.GetUnderlyingValue(eTestEnum.B)); - Assert.AreEqual(3, EnumUtils.GetUnderlyingValue(eTestEnum.C)); - } - [Test] public void GetValuesGenericTest() { @@ -122,7 +113,7 @@ namespace ICD.Common.Utils.Tests [Test] public void GetValuesExceptNoneTest() { - object[] values = EnumUtils.GetValuesExceptNone(typeof(eTestEnum)).ToArray(); + eTestEnum[] values = EnumUtils.GetValuesExceptNone(typeof(eTestEnum)).Cast().ToArray(); Assert.AreEqual(3, values.Length); Assert.IsFalse(values.Contains(eTestEnum.None)); diff --git a/ICD.Common.Utils/EnumUtils.cs b/ICD.Common.Utils/EnumUtils.cs index eb8cde5..ce9ca2d 100644 --- a/ICD.Common.Utils/EnumUtils.cs +++ b/ICD.Common.Utils/EnumUtils.cs @@ -14,16 +14,16 @@ namespace ICD.Common.Utils { public static class EnumUtils { - private static readonly Dictionary s_EnumValuesCache; - private static readonly Dictionary> s_EnumFlagsCache; + private static readonly Dictionary s_EnumValuesCache; + private static readonly Dictionary> s_EnumFlagsCache; /// /// Static constructor. /// static EnumUtils() { - s_EnumValuesCache = new Dictionary(); - s_EnumFlagsCache = new Dictionary>(); + s_EnumValuesCache = new Dictionary(); + s_EnumFlagsCache = new Dictionary>(); } /// @@ -75,12 +75,12 @@ namespace ICD.Common.Utils if (!IsFlagsEnum()) return GetValues().Any(v => v.Equals(value)); - int valueInt = (int)GetUnderlyingValue(value); + int valueInt = (int)(object)value; // Check if all of the flag values are defined foreach (T flag in GetFlags(value)) { - int flagInt = (int)GetUnderlyingValue(flag); + int flagInt = (int)(object)flag; valueInt = valueInt - flagInt; } @@ -89,23 +89,6 @@ namespace ICD.Common.Utils #region Values - /// - /// Gets the underlying value of the enum. - /// - /// - /// - public static object GetUnderlyingValue(T value) - { - if (!IsEnumType(typeof(T))) - throw new InvalidOperationException(string.Format("{0} is not an enum", typeof(T).Name)); - -#if SIMPLSHARP - return Convert.ChangeType(value, ToEnum(value).GetTypeCode(), CultureInfo.InvariantCulture); -#else - return Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())); -#endif - } - /// /// Gets the values from an enumeration. /// @@ -121,16 +104,16 @@ namespace ICD.Common.Utils /// /// /// - public static IEnumerable GetValues(Type type) + public static IEnumerable GetValues(Type type) { if (type == null) throw new ArgumentNullException("type"); // Reflection is slow and this method is called a lot, so we cache the results. - object[] cache; + int[] cache; if (!s_EnumValuesCache.TryGetValue(type, out cache)) { - cache = GetValuesUncached(type).ToArray(); + cache = GetValuesUncached(type).Cast().ToArray(); s_EnumValuesCache[type] = cache; } @@ -191,7 +174,7 @@ namespace ICD.Common.Utils /// /// /// - public static IEnumerable GetValuesExceptNone(Type type) + public static IEnumerable GetValuesExceptNone(Type type) { if (type == null) throw new ArgumentNullException("type"); @@ -199,7 +182,7 @@ namespace ICD.Common.Utils if (!IsEnumType(type)) throw new InvalidOperationException(string.Format("{0} is not an enum", type.Name)); - return GetValues(type).Where(v => (int)v != 0); + return GetValues(type).Where(v => v != 0); } #endregion @@ -284,21 +267,22 @@ namespace ICD.Common.Utils throw new ArgumentException(string.Format("{0} is not an enum", value == null ? "NULL" : value.GetType().Name), "value"); Type type = typeof(T); + int valueInt = (int)(object)value; - Dictionary cache; + Dictionary cache; if (!s_EnumFlagsCache.TryGetValue(type, out cache)) { - cache = new Dictionary(); + cache = new Dictionary(); s_EnumFlagsCache[type] = cache; } - object[] flags; - if (!cache.TryGetValue(value, out flags)) + int[] flags; + if (!cache.TryGetValue(valueInt, out flags)) { flags = GetValues().Where(e => HasFlag(value, e)) - .Cast() + .Cast() .ToArray(); - cache[value] = flags; + cache[valueInt] = flags; } return flags.Cast();