diff --git a/ICD.Common.Utils.Tests/EnumUtilsTest.cs b/ICD.Common.Utils.Tests/EnumUtilsTest.cs index 2325f7a..35a4724 100644 --- a/ICD.Common.Utils.Tests/EnumUtilsTest.cs +++ b/ICD.Common.Utils.Tests/EnumUtilsTest.cs @@ -71,6 +71,9 @@ namespace ICD.Common.Utils.Tests { Assert.IsFalse(EnumUtils.IsDefined((eTestEnum)20)); Assert.IsTrue(EnumUtils.IsDefined((eTestEnum)2)); + + Assert.IsFalse(EnumUtils.IsDefined((eTestFlagsEnum)8)); + Assert.IsTrue(EnumUtils.IsDefined((eTestFlagsEnum)3)); } #region Values @@ -262,18 +265,29 @@ namespace ICD.Common.Utils.Tests { Assert.AreEqual(eTestEnum.A, EnumUtils.ParseStrict("1", false)); Assert.Throws(() => EnumUtils.ParseStrict("4", false)); + + Assert.AreEqual(eTestFlagsEnum.A | eTestFlagsEnum.B, EnumUtils.ParseStrict("3", false)); + Assert.Throws(() => EnumUtils.ParseStrict("8", false)); } [Test] public void TryParseStrictGenericTest() { - eTestEnum output; + eTestEnum outputA; - Assert.AreEqual(true, EnumUtils.TryParseStrict("1", false, out output)); - Assert.AreEqual(eTestEnum.A, output); + Assert.AreEqual(true, EnumUtils.TryParseStrict("1", false, out outputA)); + Assert.AreEqual(eTestEnum.A, outputA); - Assert.AreEqual(false, EnumUtils.TryParseStrict("4", false, out output)); - Assert.AreEqual(eTestEnum.None, output); + Assert.AreEqual(false, EnumUtils.TryParseStrict("4", false, out outputA)); + Assert.AreEqual(eTestEnum.None, outputA); + + eTestFlagsEnum outputB; + + Assert.AreEqual(true, EnumUtils.TryParseStrict("3", false, out outputB)); + Assert.AreEqual(eTestFlagsEnum.A | eTestFlagsEnum.B, outputB); + + Assert.AreEqual(false, EnumUtils.TryParseStrict("8", false, out outputB)); + Assert.AreEqual(eTestFlagsEnum.None, outputB); } [Test] diff --git a/ICD.Common.Utils/EnumUtils.cs b/ICD.Common.Utils/EnumUtils.cs index 1a07de3..aefcfb4 100644 --- a/ICD.Common.Utils/EnumUtils.cs +++ b/ICD.Common.Utils/EnumUtils.cs @@ -52,19 +52,31 @@ namespace ICD.Common.Utils return value != null && IsEnumType(value.GetType()); } - /// - /// Returns true if the given value is defined as part of the given enum type. - /// - /// - /// - /// - public static bool IsDefined(T value) - { - if (!IsEnumType(typeof(T))) - throw new InvalidOperationException(string.Format("{0} is not an enum", typeof(T).Name)); + /// + /// Returns true if the given value is defined as part of the given enum type. + /// + /// + /// + /// + public static bool IsDefined(T value) + { + if (!IsEnumType(typeof(T))) + throw new InvalidOperationException(string.Format("{0} is not an enum", typeof(T).Name)); - return GetValues().Any(v => v.Equals(value)); - } + if (!IsFlagsEnum()) + return GetValues().Any(v => v.Equals(value)); + + int valueInt = (int)GetUnderlyingValue(value); + + // Check if all of the flag values are defined + foreach (T flag in GetFlags(value)) + { + int flagInt = (int)GetUnderlyingValue(flag); + valueInt = valueInt - flagInt; + } + + return valueInt == 0; + } #region Values @@ -384,27 +396,24 @@ namespace ICD.Common.Utils #region Conversion - /// - /// Shorthand for parsing string to enum. - /// - /// - /// - /// - /// - public static T Parse(string data, bool ignoreCase) + /// + /// Shorthand for parsing string to enum. + /// + /// + /// + /// + /// + public static T Parse(string data, bool ignoreCase) { if (!IsEnumType()) throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name)); - try - { - return (T)Enum.Parse(typeof(T), data, ignoreCase); - } - catch (Exception e) - { - throw new FormatException( - string.Format("Failed to parse {0} as {1}", StringUtils.ToRepresentation(data), typeof(T).Name), e); - } + T output; + if (TryParse(data, ignoreCase, out output)) + return output; + + string message = string.Format("Failed to parse {0} as {1}", StringUtils.ToRepresentation(data), typeof(T).Name); + throw new FormatException(message); } /// @@ -424,7 +433,7 @@ namespace ICD.Common.Utils try { - result = Parse(data, ignoreCase); + result = (T)Enum.Parse(typeof(T), data, ignoreCase); return true; } catch (Exception)