From 979cc03d98b8996644fe44bfa7087693f9e7ee60 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Fri, 28 Jun 2024 23:33:59 +0200 Subject: [PATCH] fixed some ToString inconsistencies compared to regular enums --- DynamicEnums/DynamicEnum.cs | 26 +++++++++++++++++++------- README.md | 2 +- Tests/EnumTests.cs | 10 ++++++++-- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/DynamicEnums/DynamicEnum.cs b/DynamicEnums/DynamicEnum.cs index 2d6cc04..fb30ddb 100644 --- a/DynamicEnums/DynamicEnum.cs +++ b/DynamicEnums/DynamicEnum.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Numerics; using System.Reflection; +using System.Text; #if NET6_0_OR_GREATER using System.Diagnostics.CodeAnalysis; @@ -85,14 +86,25 @@ namespace DynamicEnums { /// A string that represents the current object. public override string ToString() { if (this.name == null) { - var included = new List(); - if (DynamicEnum.GetValue(this) != 0) { - foreach (var v in DynamicEnum.GetValues(this.GetType())) { - if (this.HasAllFlags(v) && DynamicEnum.GetValue(v) != 0) - included.Add(v); + // Enum ToString remarks: https://learn.microsoft.com/en-us/dotnet/api/system.enum.tostring + // If the FlagsAttribute is not applied to this enumerated type and there is a named constant equal to the value of this instance, then the return value is a string containing the name of the constant. + // If the FlagsAttribute is applied and there is a combination of one or more named constants equal to the value of this instance, then the return value is a string containing a delimiter-separated list of the names of the constants. + // Otherwise, the return value is the string representation of the numeric value of this instance. + + var included = new StringBuilder(); + var remain = DynamicEnum.GetValue(this); + foreach (var other in DynamicEnum.GetValues(this.GetType())) { + if (this.HasAllFlags(other)) { + var otherValue = DynamicEnum.GetValue(other); + if (otherValue != 0) { + if (included.Length > 0) + included.Append(" | "); + included.Append(other); + remain &= ~otherValue; + } } } - this.name = included.Count > 0 ? string.Join(" | ", included) : DynamicEnum.GetValue(this).ToString(); + this.name = included.Length > 0 && remain == 0 ? included.ToString() : DynamicEnum.GetValue(this).ToString(); } return this.name; } @@ -458,4 +470,4 @@ namespace DynamicEnums { } } -} \ No newline at end of file +} diff --git a/README.md b/README.md index 6205b81..541309f 100644 --- a/README.md +++ b/README.md @@ -58,4 +58,4 @@ MyEnum parsed1 = DynamicEnum.Parse("FlagOne"); MyEnum parsed2 = DynamicEnum.Parse("FlagOne | FlagThree"); ``` -You can also check out [the tests](https://github.com/Ellpeck/DynamicEnums/tree/main/Tests) for some more complex examples. \ No newline at end of file +You can also check out [the tests](https://github.com/Ellpeck/DynamicEnums/tree/main/Tests) for some more complex examples. diff --git a/Tests/EnumTests.cs b/Tests/EnumTests.cs index a789ec8..79dbea9 100644 --- a/Tests/EnumTests.cs +++ b/Tests/EnumTests.cs @@ -32,6 +32,7 @@ public class EnumTests { var flags = new TestDynamicEnum[100]; for (var i = 0; i < flags.Length; i++) flags[i] = DynamicEnum.AddFlag("Flag" + i); + var zero = DynamicEnum.Add("Zero", 0); var combined = DynamicEnum.Add("Combined", DynamicEnum.GetValue(DynamicEnum.Or(flags[7], flags[13]))); Assert.AreEqual(DynamicEnum.GetValue(flags[7]), BigInteger.One << 7); @@ -53,8 +54,13 @@ public class EnumTests { Assert.AreEqual(DynamicEnum.Parse("Flag24"), flags[24]); Assert.AreEqual(DynamicEnum.Parse("Flag24 | Flag43"), DynamicEnum.Or(flags[24], flags[43])); + Assert.AreEqual(flags[24].ToString(), "Flag24"); + Assert.AreEqual(zero.ToString(), "Zero"); + Assert.AreEqual(DynamicEnum.GetEnumValue(0).ToString(), "Zero"); Assert.AreEqual(DynamicEnum.Or(flags[24], flags[43]).ToString(), "Flag24 | Flag43"); + Assert.AreEqual(DynamicEnum.Or(flags[24], DynamicEnum.GetEnumValue(new BigInteger(1) << 99)).ToString(), "Flag24 | Flag99"); + Assert.AreEqual(DynamicEnum.Or(flags[24], DynamicEnum.GetEnumValue(new BigInteger(1) << 101)).ToString(), (DynamicEnum.GetValue(flags[24]) | new BigInteger(1) << 101).ToString()); Assert.True(DynamicEnum.IsDefined(flags[27])); Assert.True(DynamicEnum.IsDefined(combined)); @@ -63,7 +69,7 @@ public class EnumTests { Assert.AreEqual( new[] {flags[0], flags[7], flags[13], combined}, - DynamicEnum.GetFlags(DynamicEnum.Or(DynamicEnum.Or(flags[0], flags[13]), flags[7]))); + DynamicEnum.GetFlags(DynamicEnum.Or(DynamicEnum.Or(flags[0], flags[13]), flags[7]), false)); Assert.AreEqual( new[] {flags[0], flags[7], flags[13]}, @@ -90,4 +96,4 @@ public class EnumTests { } -} \ No newline at end of file +}