diff --git a/src/NetEscapades.EnumGenerators.Generators/SourceGenerationHelper.cs b/src/NetEscapades.EnumGenerators.Generators/SourceGenerationHelper.cs
index 866e0d4..918c706 100644
--- a/src/NetEscapades.EnumGenerators.Generators/SourceGenerationHelper.cs
+++ b/src/NetEscapades.EnumGenerators.Generators/SourceGenerationHelper.cs
@@ -94,7 +94,35 @@ namespace
/// This is a non-distinct count of defined names.
///
public const int Length =
- """).Append(enumToGenerate.Names.Count).Append(";").Append(
+ """).Append(enumToGenerate.Names.Count).Append(";");
+
+ if (enumToGenerate.HasFlags)
+ {
+ sb.Append(
+ """
+
+
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const
+ """).Append(' ').Append(fullyQualifiedName).Append(" All = ");
+
+ var first = true;
+ foreach (var member in enumToGenerate.Names)
+ {
+ if (!first)
+ {
+ sb.Append(" | ");
+ }
+ first = false;
+ sb.Append(fullyQualifiedName).Append('.').AppendIdentifier(member.Key);
+ }
+
+ sb.Append(';');
+ }
+
+ sb.Append(
"""
@@ -550,7 +578,123 @@ public static bool HasFlagFast(this
"""
flag)
=> flag == 0 ? true : (value & flag) == flag;
+
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this
+ """).Append(' ').Append(fullyQualifiedName).Append(" value, ").Append(fullyQualifiedName)
+ .Append(
+ """
+ otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
""");
+
+ // Collect single-bit flag members (powers of two) and build a mask of all defined bits.
+ // Composite members are allowed as long as every bit they set is also a defined single-bit flag.
+ // Members with bits outside the defined mask disqualify the enum from TryGetFlags emission.
+ List<(string Name, ulong Value)>? singleBitFlags = null;
+ var seenBitValues = new HashSet();
+ ulong definedMask = 0;
+ foreach (var member in enumToGenerate.Names)
+ {
+ var bits = ToUInt64BitPattern(member.Value.ConstantValue);
+ if (bits == 0)
+ {
+ // Zero-valued members (e.g. None) are allowed but not emitted.
+ continue;
+ }
+ if ((bits & (bits - 1)) == 0 && seenBitValues.Add(bits))
+ {
+ singleBitFlags ??= new List<(string, ulong)>();
+ singleBitFlags.Add((member.Key, bits));
+ definedMask |= bits;
+ }
+ }
+
+ // Verify every non-zero member value is a subset of the defined-bit mask.
+ // Catches members with bits that don't correspond to any single-bit flag.
+ var hasInvalidValue = false;
+ if (singleBitFlags is { Count: > 0 })
+ {
+ foreach (var member in enumToGenerate.Names)
+ {
+ var bits = ToUInt64BitPattern(member.Value.ConstantValue);
+ if (bits != 0 && (bits & ~definedMask) != 0)
+ {
+ hasInvalidValue = true;
+ break;
+ }
+ }
+ }
+
+ if (!hasInvalidValue && singleBitFlags is { Count: > 0 })
+ {
+ singleBitFlags.Sort((a, b) => a.Value.CompareTo(b.Value));
+
+ sb.Append(
+ """
+
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount =
+ """).Append(' ').Append(singleBitFlags.Count).Append(';');
+
+ sb.Append(
+ """
+
+
+ #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this
+ """).Append(' ').Append(fullyQualifiedName).Append(" value, global::System.Span<").Append(fullyQualifiedName).Append(
+ """
+ > buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ """);
+
+ foreach (var flag in singleBitFlags)
+ {
+ sb.Append("\n if ((value & ")
+ .Append(fullyQualifiedName).Append('.').AppendIdentifier(flag.Name)
+ .Append(") == ")
+ .Append(fullyQualifiedName).Append('.').AppendIdentifier(flag.Name)
+ .Append(")\n buffer[count++] = ")
+ .Append(fullyQualifiedName).Append('.').AppendIdentifier(flag.Name)
+ .Append(';');
+ }
+
+ sb.Append(
+ """
+
+ return true;
+ }
+ #endif
+ """);
+ }
}
sb.Append(
@@ -2380,6 +2524,20 @@ private static StringBuilder AppendIdentifier(this StringBuilder sb, string iden
return sb.Append(identifier);
}
+ private static ulong ToUInt64BitPattern(object value)
+ => value switch
+ {
+ sbyte v => (byte)v,
+ byte v => v,
+ short v => (ushort)v,
+ ushort v => v,
+ int v => (uint)v,
+ uint v => v,
+ long v => unchecked((ulong)v),
+ ulong v => v,
+ _ => 0UL,
+ };
+
private enum AlternativeMethodChoice
{
None,
diff --git a/tests/NetEscapades.EnumGenerators.IntegrationTests/BitFlagsEnumExtensionsTests.cs b/tests/NetEscapades.EnumGenerators.IntegrationTests/BitFlagsEnumExtensionsTests.cs
new file mode 100644
index 0000000..d5acec0
--- /dev/null
+++ b/tests/NetEscapades.EnumGenerators.IntegrationTests/BitFlagsEnumExtensionsTests.cs
@@ -0,0 +1,76 @@
+using FluentAssertions;
+using System;
+using Xunit;
+
+#if INTEGRATION_TESTS
+namespace NetEscapades.EnumGenerators.IntegrationTests;
+#elif PRIVATEASSETS_INTEGRATION_TESTS
+namespace NetEscapades.EnumGenerators.PrivateAssets.IntegrationTests;
+#elif NETSTANDARD_INTEGRATION_TESTS
+namespace NetEscapades.EnumGenerators.NetStandard.IntegrationTests;
+#elif NETSTANDARD_SYSTEMMEMORY_INTEGRATION_TESTS
+namespace NetEscapades.EnumGenerators.NetStandard.SystemMemory.IntegrationTests;
+#elif INTERCEPTOR_TESTS
+namespace NetEscapades.EnumGenerators.Interceptors.IntegrationTests;
+#elif NUGET_INTEGRATION_TESTS
+namespace NetEscapades.EnumGenerators.Nuget.IntegrationTests;
+#elif NUGET_INTERCEPTOR_TESTS
+namespace NetEscapades.EnumGenerators.Nuget.Interceptors.IntegrationTests;
+#elif NUGET_SYSTEMMEMORY_INTEGRATION_TESTS
+namespace NetEscapades.EnumGenerators.Nuget.SystemMemory.IntegrationTests;
+#elif NUGET_SYSTEMMEMORY_PRIVATEASSETS_INTEGRATION_TESTS
+namespace NetEscapades.EnumGenerators.Nuget.SystemMemory.PrivateAssets.IntegrationTests;
+#else
+#error Unknown integration tests
+#endif
+
+public class BitFlagsEnumExtensionsTests
+{
+ [Fact]
+ public void DistinctFlagCountExcludesNone()
+ {
+ BitFlagsEnumExtensions.DistinctFlagCount.Should().Be(4);
+ }
+
+#if READONLYSPAN
+ public static TheoryData TryGetFlagsData => new()
+ {
+ // Single flag → itself
+ { BitFlagsEnum.First, 1, new[] { BitFlagsEnum.First } },
+ // Multiple flags — bit-value order
+ { BitFlagsEnum.First | BitFlagsEnum.Third, 2, new[] { BitFlagsEnum.First, BitFlagsEnum.Third } },
+ // None → empty output
+ { BitFlagsEnum.None, 0, Array.Empty() },
+ // Undefined bits silently dropped (16 is not defined)
+ { (BitFlagsEnum)17, 1, new[] { BitFlagsEnum.First } },
+ // Only undefined bits → empty output
+ { (BitFlagsEnum)16, 0, Array.Empty() },
+ // All defined flags set → 4 single-bit members
+ { BitFlagsEnumExtensions.All, 4,
+ new[] { BitFlagsEnum.First, BitFlagsEnum.Second, BitFlagsEnum.Third, BitFlagsEnum.Fourth } },
+ // All bits set across underlying type → still just the 4 defined flags
+ { (BitFlagsEnum)0xFF, 4,
+ new[] { BitFlagsEnum.First, BitFlagsEnum.Second, BitFlagsEnum.Third, BitFlagsEnum.Fourth } },
+ };
+
+ [Theory]
+ [MemberData(nameof(TryGetFlagsData))]
+ public void TryGetFlags(BitFlagsEnum value, int expectedCount, BitFlagsEnum[] expectedFlags)
+ {
+ Span buffer = stackalloc BitFlagsEnum[BitFlagsEnumExtensions.DistinctFlagCount];
+ var result = value.TryGetFlags(buffer, out var count);
+ result.Should().BeTrue();
+ count.Should().Be(expectedCount);
+ buffer.Slice(0, count).ToArray().Should().Equal(expectedFlags);
+ }
+
+ [Fact]
+ public void TryGetFlags_BufferSmallerThanDistinctFlagCount_ReturnsFalse()
+ {
+ Span buffer = stackalloc BitFlagsEnum[BitFlagsEnumExtensions.DistinctFlagCount - 1];
+ var result = BitFlagsEnum.First.TryGetFlags(buffer, out var count);
+ result.Should().BeFalse();
+ count.Should().Be(0);
+ }
+#endif
+}
diff --git a/tests/NetEscapades.EnumGenerators.IntegrationTests/Enums.cs b/tests/NetEscapades.EnumGenerators.IntegrationTests/Enums.cs
index 2be7a12..0059824 100644
--- a/tests/NetEscapades.EnumGenerators.IntegrationTests/Enums.cs
+++ b/tests/NetEscapades.EnumGenerators.IntegrationTests/Enums.cs
@@ -167,6 +167,17 @@ public enum FlagsEnum
ThirdAndFourth = Third | Fourth,
}
+ [EnumExtensions]
+ [Flags]
+ public enum BitFlagsEnum
+ {
+ None = 0,
+ First = 1 << 0,
+ Second = 1 << 1,
+ Third = 1 << 2,
+ Fourth = 1 << 3,
+ }
+
[EnumExtensions(MetadataSource = MetadataSource.DescriptionAttribute)]
public enum StringTesting
{
diff --git a/tests/NetEscapades.EnumGenerators.IntegrationTests/FlagsEnumExtensionsTests.cs b/tests/NetEscapades.EnumGenerators.IntegrationTests/FlagsEnumExtensionsTests.cs
index c980c41..21cfbb8 100644
--- a/tests/NetEscapades.EnumGenerators.IntegrationTests/FlagsEnumExtensionsTests.cs
+++ b/tests/NetEscapades.EnumGenerators.IntegrationTests/FlagsEnumExtensionsTests.cs
@@ -139,7 +139,104 @@ public void HasFlags(FlagsEnum value, FlagsEnum flag)
isDefined.Should().Be(value.HasFlag(flag));
}
-
+
+ [Fact]
+ public void AllContainsFlag()
+ {
+ foreach (var flag in FlagsEnumExtensions.GetValues())
+ {
+ FlagsEnumExtensions.All.HasFlag(flag).Should().BeTrue();
+ }
+ }
+
+ [Fact]
+ public void AllHasExpectedValue()
+ {
+ ((int)FlagsEnumExtensions.All).Should().Be(0b1111); // 15
+ }
+
+ public static TheoryData HasAnyFlagsData => new()
+ {
+ // Single flag present
+ { FlagsEnum.First | FlagsEnum.Second, FlagsEnum.First, true },
+ // No queried flags present
+ { FlagsEnum.First | FlagsEnum.Second, FlagsEnum.Third, false },
+ // Partial overlap — only some flags match
+ { FlagsEnum.First, FlagsEnum.First | FlagsEnum.Third, true },
+ // None has no flags
+ { FlagsEnum.None, FlagsEnum.First, false },
+ // Querying with zero (None) — consistent with HasFlag(0) behavior
+ { FlagsEnum.First, FlagsEnum.None, true },
+ // Both zero
+ { FlagsEnum.None, FlagsEnum.None, true },
+ // Composite member overlaps
+ { FlagsEnum.Third, FlagsEnum.ThirdAndFourth, true },
+ // Composite member no overlap
+ { FlagsEnum.First, FlagsEnum.ThirdAndFourth, false },
+ // Undefined value with overlap (65 = 64|1, First = 1)
+ { (FlagsEnum)65, FlagsEnum.First, true },
+ // Undefined value no overlap
+ { (FlagsEnum)64, FlagsEnum.First, false },
+ };
+
+ [Theory]
+ [MemberData(nameof(HasAnyFlagsData))]
+ public void HasAnyFlags(FlagsEnum value, FlagsEnum otherFlags, bool expected)
+ {
+ value.HasAnyFlags(otherFlags).Should().Be(expected);
+ }
+
+ [Fact]
+ public void DistinctFlagCountCountsSingleBitFlags()
+ {
+ // First, Second, Third, Fourth — ThirdAndFourth is a composite, None is zero
+ FlagsEnumExtensions.DistinctFlagCount.Should().Be(4);
+ }
+
+#if READONLYSPAN
+ public static TheoryData TryGetFlagsData => new()
+ {
+ // Single flag
+ { FlagsEnum.First, 1, new[] { FlagsEnum.First } },
+ // Multiple flags — bit-value order
+ { FlagsEnum.First | FlagsEnum.Third, 2, new[] { FlagsEnum.First, FlagsEnum.Third } },
+ // Composite member decomposes into its constituent single-bit flags
+ { FlagsEnum.ThirdAndFourth, 2, new[] { FlagsEnum.Third, FlagsEnum.Fourth } },
+ // Combination of single-bit and composite — same as combining the bits
+ { FlagsEnum.First | FlagsEnum.ThirdAndFourth, 3,
+ new[] { FlagsEnum.First, FlagsEnum.Third, FlagsEnum.Fourth } },
+ // None → empty
+ { FlagsEnum.None, 0, Array.Empty() },
+ // Undefined bit (16) is silently dropped, defined bit (1) is kept
+ { (FlagsEnum)17, 1, new[] { FlagsEnum.First } },
+ // Only undefined bits → empty
+ { (FlagsEnum)16, 0, Array.Empty() },
+ // All defined flags set
+ { FlagsEnumExtensions.All, 4,
+ new[] { FlagsEnum.First, FlagsEnum.Second, FlagsEnum.Third, FlagsEnum.Fourth } },
+ };
+
+ [Theory]
+ [MemberData(nameof(TryGetFlagsData))]
+ public void TryGetFlags(FlagsEnum value, int expectedCount, FlagsEnum[] expectedFlags)
+ {
+ Span buffer = stackalloc FlagsEnum[FlagsEnumExtensions.DistinctFlagCount];
+ var result = value.TryGetFlags(buffer, out var count);
+ result.Should().BeTrue();
+ count.Should().Be(expectedCount);
+ buffer.Slice(0, count).ToArray().Should().Equal(expectedFlags);
+ }
+
+ [Fact]
+ public void TryGetFlags_BufferSmallerThanDistinctFlagCount_ReturnsFalse()
+ {
+ Span buffer = stackalloc FlagsEnum[FlagsEnumExtensions.DistinctFlagCount - 1];
+ var result = FlagsEnum.First.TryGetFlags(buffer, out var count);
+ result.Should().BeFalse();
+ count.Should().Be(0);
+ }
+#endif
+
private PackageEnumParseOptions Map(EnumParseOptions options)
=> new(comparisonType: options.ComparisonType,
allowMatchingMetadataAttribute: options.AllowMatchingMetadataAttribute,
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateEnumExtensionsForFlagsEnum_Params.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateEnumExtensionsForFlagsEnum_Params.verified.txt
index a5a863e..120bc4b 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateEnumExtensionsForFlagsEnum_Params.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateEnumExtensionsForFlagsEnum_Params.verified.txt
@@ -25,6 +25,11 @@ namespace MyTestNameSpace
///
public const int Length = 3;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::MyTestNameSpace.MyEnum All = global::MyTestNameSpace.MyEnum.First | global::MyTestNameSpace.MyEnum.Second | global::MyTestNameSpace.MyEnum.Third;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -103,6 +108,52 @@ namespace MyTestNameSpace
public static bool HasFlagFast(this global::MyTestNameSpace.MyEnum value, global::MyTestNameSpace.MyEnum flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::MyTestNameSpace.MyEnum value, global::MyTestNameSpace.MyEnum otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 3;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::MyTestNameSpace.MyEnum value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::MyTestNameSpace.MyEnum.First) == global::MyTestNameSpace.MyEnum.First)
+ buffer[count++] = global::MyTestNameSpace.MyEnum.First;
+ if ((value & global::MyTestNameSpace.MyEnum.Second) == global::MyTestNameSpace.MyEnum.Second)
+ buffer[count++] = global::MyTestNameSpace.MyEnum.Second;
+ if ((value & global::MyTestNameSpace.MyEnum.Third) == global::MyTestNameSpace.MyEnum.Third)
+ buffer[count++] = global::MyTestNameSpace.MyEnum.Third;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateForExternalFlagsEnum.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateForExternalFlagsEnum.verified.txt
index 7dc6b87..3e06968 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateForExternalFlagsEnum.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateForExternalFlagsEnum.verified.txt
@@ -25,6 +25,11 @@ namespace System.IO
///
public const int Length = 6;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::System.IO.FileShare All = global::System.IO.FileShare.None | global::System.IO.FileShare.Read | global::System.IO.FileShare.Write | global::System.IO.FileShare.ReadWrite | global::System.IO.FileShare.Delete | global::System.IO.FileShare.Inheritable;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -112,6 +117,54 @@ namespace System.IO
public static bool HasFlagFast(this global::System.IO.FileShare value, global::System.IO.FileShare flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::System.IO.FileShare value, global::System.IO.FileShare otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 4;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::System.IO.FileShare value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::System.IO.FileShare.Read) == global::System.IO.FileShare.Read)
+ buffer[count++] = global::System.IO.FileShare.Read;
+ if ((value & global::System.IO.FileShare.Write) == global::System.IO.FileShare.Write)
+ buffer[count++] = global::System.IO.FileShare.Write;
+ if ((value & global::System.IO.FileShare.Delete) == global::System.IO.FileShare.Delete)
+ buffer[count++] = global::System.IO.FileShare.Delete;
+ if ((value & global::System.IO.FileShare.Inheritable) == global::System.IO.FileShare.Inheritable)
+ buffer[count++] = global::System.IO.FileShare.Inheritable;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanHandleEnumsWithSameNameInDifferentNamespaces.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanHandleEnumsWithSameNameInDifferentNamespaces.verified.txt
index 3043fbb..991f911 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanHandleEnumsWithSameNameInDifferentNamespaces.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanHandleEnumsWithSameNameInDifferentNamespaces.verified.txt
@@ -26,6 +26,11 @@ namespace Foo
///
public const int Length = 3;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Foo.MyEnum All = global::Foo.MyEnum.First | global::Foo.MyEnum.Second | global::Foo.MyEnum.Third;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -104,6 +109,52 @@ namespace Foo
public static bool HasFlagFast(this global::Foo.MyEnum value, global::Foo.MyEnum flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Foo.MyEnum value, global::Foo.MyEnum otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 3;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::Foo.MyEnum value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::Foo.MyEnum.First) == global::Foo.MyEnum.First)
+ buffer[count++] = global::Foo.MyEnum.First;
+ if ((value & global::Foo.MyEnum.Second) == global::Foo.MyEnum.Second)
+ buffer[count++] = global::Foo.MyEnum.Second;
+ if ((value & global::Foo.MyEnum.Third) == global::Foo.MyEnum.Third)
+ buffer[count++] = global::Foo.MyEnum.Third;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
@@ -866,6 +917,11 @@ namespace Bar
///
public const int Length = 3;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Bar.MyEnum All = global::Bar.MyEnum.First | global::Bar.MyEnum.Second | global::Bar.MyEnum.Third;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -944,6 +1000,52 @@ namespace Bar
public static bool HasFlagFast(this global::Bar.MyEnum value, global::Bar.MyEnum flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Bar.MyEnum value, global::Bar.MyEnum otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 3;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::Bar.MyEnum value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::Bar.MyEnum.First) == global::Bar.MyEnum.First)
+ buffer[count++] = global::Bar.MyEnum.First;
+ if ((value & global::Bar.MyEnum.Second) == global::Bar.MyEnum.Second)
+ buffer[count++] = global::Bar.MyEnum.Second;
+ if ((value & global::Bar.MyEnum.Third) == global::Bar.MyEnum.Third)
+ buffer[count++] = global::Bar.MyEnum.Third;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptEnumInDifferentNamespace.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptEnumInDifferentNamespace.verified.txt
index a4155f9..f255908 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptEnumInDifferentNamespace.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptEnumInDifferentNamespace.verified.txt
@@ -26,6 +26,11 @@ namespace Bar
///
public const int Length = 3;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Foo.MyEnum All = global::Foo.MyEnum.First | global::Foo.MyEnum.Second | global::Foo.MyEnum.Third;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -104,6 +109,52 @@ namespace Bar
public static bool HasFlagFast(this global::Foo.MyEnum value, global::Foo.MyEnum flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Foo.MyEnum value, global::Foo.MyEnum otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 3;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::Foo.MyEnum value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::Foo.MyEnum.First) == global::Foo.MyEnum.First)
+ buffer[count++] = global::Foo.MyEnum.First;
+ if ((value & global::Foo.MyEnum.Second) == global::Foo.MyEnum.Second)
+ buffer[count++] = global::Foo.MyEnum.Second;
+ if ((value & global::Foo.MyEnum.Third) == global::Foo.MyEnum.Third)
+ buffer[count++] = global::Foo.MyEnum.Third;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptEnumInGlobalNamespace.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptEnumInGlobalNamespace.verified.txt
index 2208182..38501d7 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptEnumInGlobalNamespace.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptEnumInGlobalNamespace.verified.txt
@@ -24,6 +24,11 @@
///
public const int Length = 3;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::MyEnum All = global::MyEnum.First | global::MyEnum.Second | global::MyEnum.Third;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -102,6 +107,52 @@
public static bool HasFlagFast(this global::MyEnum value, global::MyEnum flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::MyEnum value, global::MyEnum otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 3;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::MyEnum value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::MyEnum.First) == global::MyEnum.First)
+ buffer[count++] = global::MyEnum.First;
+ if ((value & global::MyEnum.Second) == global::MyEnum.Second)
+ buffer[count++] = global::MyEnum.Second;
+ if ((value & global::MyEnum.Third) == global::MyEnum.Third)
+ buffer[count++] = global::MyEnum.Third;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptHasFlag.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptHasFlag.verified.txt
index 29cc515..2a130d4 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptHasFlag.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanInterceptHasFlag.verified.txt
@@ -26,6 +26,11 @@ namespace MyTestNameSpace
///
public const int Length = 3;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::MyTestNameSpace.MyEnum All = global::MyTestNameSpace.MyEnum.First | global::MyTestNameSpace.MyEnum.Second | global::MyTestNameSpace.MyEnum.Third;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -104,6 +109,52 @@ namespace MyTestNameSpace
public static bool HasFlagFast(this global::MyTestNameSpace.MyEnum value, global::MyTestNameSpace.MyEnum flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::MyTestNameSpace.MyEnum value, global::MyTestNameSpace.MyEnum otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 3;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::MyTestNameSpace.MyEnum value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::MyTestNameSpace.MyEnum.First) == global::MyTestNameSpace.MyEnum.First)
+ buffer[count++] = global::MyTestNameSpace.MyEnum.First;
+ if ((value & global::MyTestNameSpace.MyEnum.Second) == global::MyTestNameSpace.MyEnum.Second)
+ buffer[count++] = global::MyTestNameSpace.MyEnum.Second;
+ if ((value & global::MyTestNameSpace.MyEnum.Third) == global::MyTestNameSpace.MyEnum.Third)
+ buffer[count++] = global::MyTestNameSpace.MyEnum.Third;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.DoesNotInterceptEnumMarkedAsNotInterceptable.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.DoesNotInterceptEnumMarkedAsNotInterceptable.verified.txt
index 01973f1..3cc8238 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.DoesNotInterceptEnumMarkedAsNotInterceptable.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.DoesNotInterceptEnumMarkedAsNotInterceptable.verified.txt
@@ -854,6 +854,11 @@ namespace MyTestNameSpace
///
public const int Length = 3;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::MyTestNameSpace.AnotherEnum All = global::MyTestNameSpace.AnotherEnum.First | global::MyTestNameSpace.AnotherEnum.Second | global::MyTestNameSpace.AnotherEnum.Third;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -932,6 +937,50 @@ namespace MyTestNameSpace
public static bool HasFlagFast(this global::MyTestNameSpace.AnotherEnum value, global::MyTestNameSpace.AnotherEnum flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::MyTestNameSpace.AnotherEnum value, global::MyTestNameSpace.AnotherEnum otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 2;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::MyTestNameSpace.AnotherEnum value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::MyTestNameSpace.AnotherEnum.Second) == global::MyTestNameSpace.AnotherEnum.Second)
+ buffer[count++] = global::MyTestNameSpace.AnotherEnum.Second;
+ if ((value & global::MyTestNameSpace.AnotherEnum.Third) == global::MyTestNameSpace.AnotherEnum.Third)
+ buffer[count++] = global::MyTestNameSpace.AnotherEnum.Third;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.DoesNotGenerateTryGetFlagsWhenMemberHasUndefinedBits_csharp14IsSupported=False.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.DoesNotGenerateTryGetFlagsWhenMemberHasUndefinedBits_csharp14IsSupported=False.verified.txt
new file mode 100644
index 0000000..b1eb187
--- /dev/null
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.DoesNotGenerateTryGetFlagsWhenMemberHasUndefinedBits_csharp14IsSupported=False.verified.txt
@@ -0,0 +1,866 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by the NetEscapades.EnumGenerators source generator
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#nullable enable
+
+namespace Something.Blah
+{
+#pragma warning disable CS0612 // Ignore usages of obsolete members or enums
+#pragma warning disable CS0618 // Ignore usages of obsolete members or enums
+ ///
+ /// Extension methods for
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("NetEscapades.EnumGenerators", "FIXED_VERSION")]
+ public static partial class ShortName
+ {
+ ///
+ /// The number of members in the enum.
+ /// This is a non-distinct count of defined names.
+ ///
+ public const int Length = 4;
+
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Something.Blah.ShortName All = global::Something.Blah.ShortName.None | global::Something.Blah.ShortName.First | global::Something.Blah.ShortName.Second | global::Something.Blah.ShortName.Odd;
+
+ ///
+ /// Returns the string representation of the value.
+ /// Directly equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The string representation of the value, the same as that returned by ToString()
+ public static string ToStringFast(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => nameof(global::Something.Blah.ShortName.None),
+ global::Something.Blah.ShortName.First => nameof(global::Something.Blah.ShortName.First),
+ global::Something.Blah.ShortName.Second => nameof(global::Something.Blah.ShortName.Second),
+ global::Something.Blah.ShortName.Odd => nameof(global::Something.Blah.ShortName.Odd),
+ _ => value.ToString(),
+ };
+
+ ///
+ /// Returns the string representation of the value.
+ /// Directly equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The options to use when serializing the enum
+ /// The string representation of the value, using the provided options.
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static string ToStringFast(this global::Something.Blah.ShortName value, global::NetEscapades.EnumGenerators.SerializationOptions options)
+ => options.Transform switch
+ {
+ global::NetEscapades.EnumGenerators.SerializationTransform.LowerInvariant => value.ToStringFastLowerInvariant(),
+ global::NetEscapades.EnumGenerators.SerializationTransform.UpperInvariant => value.ToStringFastUpperInvariant(),
+ _ => value.ToStringFast(),
+ };
+
+ private static string ToStringFastLowerInvariant(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => "none",
+ global::Something.Blah.ShortName.First => "first",
+ global::Something.Blah.ShortName.Second => "second",
+ global::Something.Blah.ShortName.Odd => "odd",
+ _ => value.ToString().ToLowerInvariant(),
+ };
+
+ private static string ToStringFastUpperInvariant(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => "NONE",
+ global::Something.Blah.ShortName.First => "FIRST",
+ global::Something.Blah.ShortName.Second => "SECOND",
+ global::Something.Blah.ShortName.Odd => "ODD",
+ _ => value.ToString().ToUpperInvariant(),
+ };
+
+ ///
+ /// Returns the string representation of the value.
+ /// If the member is decorated with the attribute
+ /// then that value is returned. Otherwise returns uses the name of the member,
+ /// equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// If uses the value provided in the
+ /// attribute as the string representation of the member.
+ /// If , always uses the name of the member, the same as if ToString() was called.
+ /// The string representation of the value
+ public static string ToStringFast(this global::Something.Blah.ShortName value, bool useMetadataAttributes)
+ => value.ToStringFast();
+
+ ///
+ /// Determines whether one or more bit fields are set in the current instance.
+ /// Equivalent to calling on .
+ ///
+ /// The value of the instance to investigate
+ /// The flag to check for
+ /// if the fields set in the flag are also set in the current instance; otherwise .
+ /// If the underlying value of is zero, the method returns true.
+ /// This is consistent with the behaviour of
+ public static bool HasFlagFast(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName flag)
+ => flag == 0 ? true : (value & flag) == flag;
+
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// Cast a value of to the underlying type (int).
+ /// This is mainly a convenience method.
+ ///
+ /// The value of cast to the underlying type.
+ public static int AsUnderlyingType(this global::Something.Blah.ShortName value)
+ {
+ return (int) value;
+ }
+
+ ///
+ /// Returns a boolean telling whether the given enum value exists in the enumeration.
+ ///
+ /// The value to check if it's defined
+ /// if the value exists in the enumeration, otherwise
+ public static bool IsDefined(global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => true,
+ global::Something.Blah.ShortName.First => true,
+ global::Something.Blah.ShortName.Second => true,
+ global::Something.Blah.ShortName.Odd => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration.
+ ///
+ /// The name to check if it's defined
+ /// if a member with the name exists in the enumeration, otherwise
+ public static bool IsDefined(string name)
+ => name switch
+ {
+ nameof(global::Something.Blah.ShortName.None) => true,
+ nameof(global::Something.Blah.ShortName.First) => true,
+ nameof(global::Something.Blah.ShortName.Second) => true,
+ nameof(global::Something.Blah.ShortName.Odd) => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or if a member decorated with
+ /// with the required name exists.
+ ///
+ /// The name to check if it's defined
+ /// If ,
+ /// considers the value of
+ /// instead of the member name, otherwise ignores them
+ /// if a member with the name exists in the enumeration, or a member is decorated
+ /// with a [Display] attribute with the name, otherwise
+ public static bool IsDefined(string name, bool allowMatchingMetadataAttribute)
+ => IsDefined(name);
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration
+ ///
+ /// The name to check if it's defined
+ /// if a member with the name exists in the enumeration, otherwise
+ public static bool IsDefined(in global::System.ReadOnlySpan name)
+ => name switch
+ {
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.None)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.First)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Second)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Odd)), global::System.StringComparison.Ordinal) => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or optionally if a member decorated with
+ /// exists. Slower then the overload, but doesn't allocate memory./>
+ ///
+ /// The name to check if it's defined
+ /// If , considers the value of metadata attributes,otherwise ignores them
+ /// if a member with the name exists in the enumeration, or a member is decorated
+ /// with a [Display] attribute with the name, otherwise
+ public static bool IsDefined(in global::System.ReadOnlySpan name, bool allowMatchingMetadataAttribute)
+ => IsDefined(name);
+#endif
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name)
+ => TryParse(name, out var value, new global::NetEscapades.EnumGenerators.EnumParseOptions()) ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal))
+ ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in metadata attributes such as
+ /// [Display] attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute)) ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ => TryParse(
+ name,
+ out var value,
+ options) ? value : ThrowValueNotFound(name);
+
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
+#endif
+ private static global::Something.Blah.ShortName ThrowValueNotFound(string? name)
+ => throw new global::System.ArgumentException($"Requested value '{name}' was not found.");
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value)
+ => TryParse(name, out value, new global::NetEscapades.EnumGenerators.EnumParseOptions());
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase)
+ => TryParse(name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal));
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If ,
+ /// considers the value included in attribute
+ /// when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute));
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ {
+ switch (name)
+ {
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.None), options.ComparisonType):
+ value = global::Something.Blah.ShortName.None;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.First), options.ComparisonType):
+ value = global::Something.Blah.ShortName.First;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.Second), options.ComparisonType):
+ value = global::Something.Blah.ShortName.Second;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.Odd), options.ComparisonType):
+ value = global::Something.Blah.ShortName.Odd;
+ return true;
+ case string s when options.EnableNumberParsing && int.TryParse(name, out var val):
+ value = (global::Something.Blah.ShortName)val;
+ return true;
+ default:
+ value = default;
+ return false;
+ }
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions())
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal))
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute))
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, disable number parsing in the parameter.
+
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ => TryParse(
+ name,
+ out var value,
+ options) ? value : ThrowValueNotFound(name);
+
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
+#endif
+ private static global::Something.Blah.ShortName ThrowValueNotFound(in global::System.ReadOnlySpan name)
+#if NET6_0_OR_GREATER
+ => throw new global::System.ArgumentException($"Requested value '{name}' was not found.");
+#else
+ => throw new global::System.ArgumentException($"Requested value '{name.ToString()}' was not found.");
+#endif
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName value)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions());
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal));
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName result,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out result,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute));
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, disable number parsing in the parameter.
+
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName result,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ {
+ switch (name)
+ {
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.None)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.None;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.First)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.First;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Second)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.Second;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Odd)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.Odd;
+ return true;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ case global::System.ReadOnlySpan current when options.EnableNumberParsing && int.TryParse(name, out var numericResult):
+#else
+ // TryParse with ReadOnlySpan is not available, so we have to call ToString()
+ case global::System.ReadOnlySpan current when options.EnableNumberParsing && int.TryParse(name.ToString(), out var numericResult):
+#endif
+ result = (global::Something.Blah.ShortName)numericResult;
+ return true;
+ default:
+ result = default;
+ return false;
+ }
+ }
+#endif
+
+ ///
+ /// Retrieves an array of the values of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the values defined in
+ public static global::Something.Blah.ShortName[] GetValues()
+ => new[]
+ {
+ global::Something.Blah.ShortName.None,
+ global::Something.Blah.ShortName.First,
+ global::Something.Blah.ShortName.Second,
+ global::Something.Blah.ShortName.Odd,
+ };
+
+ ///
+ /// Retrieves an array of the underlying-values of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the underlying-values defined in
+ public static int[] GetValuesAsUnderlyingType()
+ => new[]
+ {
+ (int) global::Something.Blah.ShortName.None,
+ (int) global::Something.Blah.ShortName.First,
+ (int) global::Something.Blah.ShortName.Second,
+ (int) global::Something.Blah.ShortName.Odd,
+ };
+
+ ///
+ /// Retrieves an array of the names of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the names of the members defined in
+ public static string[] GetNames()
+ => new[]
+ {
+ nameof(global::Something.Blah.ShortName.None),
+ nameof(global::Something.Blah.ShortName.First),
+ nameof(global::Something.Blah.ShortName.Second),
+ nameof(global::Something.Blah.ShortName.Odd),
+ };
+ }
+#pragma warning restore CS0612 // Ignore usages of obsolete members or enums
+#pragma warning restore CS0618 // Ignore usages of obsolete members or enums
+}
\ No newline at end of file
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.DoesNotGenerateTryGetFlagsWhenMemberHasUndefinedBits_csharp14IsSupported=True.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.DoesNotGenerateTryGetFlagsWhenMemberHasUndefinedBits_csharp14IsSupported=True.verified.txt
new file mode 100644
index 0000000..d9ce603
--- /dev/null
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.DoesNotGenerateTryGetFlagsWhenMemberHasUndefinedBits_csharp14IsSupported=True.verified.txt
@@ -0,0 +1,871 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by the NetEscapades.EnumGenerators source generator
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#nullable enable
+
+namespace Something.Blah
+{
+#pragma warning disable CS0612 // Ignore usages of obsolete members or enums
+#pragma warning disable CS0618 // Ignore usages of obsolete members or enums
+ ///
+ /// Extension methods for
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("NetEscapades.EnumGenerators", "FIXED_VERSION")]
+ public static partial class ShortName
+ {
+ ///
+ /// The number of members in the enum.
+ /// This is a non-distinct count of defined names.
+ ///
+ public const int Length = 4;
+
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Something.Blah.ShortName All = global::Something.Blah.ShortName.None | global::Something.Blah.ShortName.First | global::Something.Blah.ShortName.Second | global::Something.Blah.ShortName.Odd;
+
+ ///
+ /// Returns the string representation of the value.
+ /// Directly equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The string representation of the value, the same as that returned by ToString()
+ public static string ToStringFast(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => nameof(global::Something.Blah.ShortName.None),
+ global::Something.Blah.ShortName.First => nameof(global::Something.Blah.ShortName.First),
+ global::Something.Blah.ShortName.Second => nameof(global::Something.Blah.ShortName.Second),
+ global::Something.Blah.ShortName.Odd => nameof(global::Something.Blah.ShortName.Odd),
+ _ => value.ToString(),
+ };
+
+ ///
+ /// Returns the string representation of the value.
+ /// Directly equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The options to use when serializing the enum
+ /// The string representation of the value, using the provided options.
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static string ToStringFast(this global::Something.Blah.ShortName value, global::NetEscapades.EnumGenerators.SerializationOptions options)
+ => options.Transform switch
+ {
+ global::NetEscapades.EnumGenerators.SerializationTransform.LowerInvariant => value.ToStringFastLowerInvariant(),
+ global::NetEscapades.EnumGenerators.SerializationTransform.UpperInvariant => value.ToStringFastUpperInvariant(),
+ _ => value.ToStringFast(),
+ };
+
+ private static string ToStringFastLowerInvariant(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => "none",
+ global::Something.Blah.ShortName.First => "first",
+ global::Something.Blah.ShortName.Second => "second",
+ global::Something.Blah.ShortName.Odd => "odd",
+ _ => value.ToString().ToLowerInvariant(),
+ };
+
+ private static string ToStringFastUpperInvariant(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => "NONE",
+ global::Something.Blah.ShortName.First => "FIRST",
+ global::Something.Blah.ShortName.Second => "SECOND",
+ global::Something.Blah.ShortName.Odd => "ODD",
+ _ => value.ToString().ToUpperInvariant(),
+ };
+
+ ///
+ /// Returns the string representation of the value.
+ /// If the member is decorated with the attribute
+ /// then that value is returned. Otherwise returns uses the name of the member,
+ /// equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// If uses the value provided in the
+ /// attribute as the string representation of the member.
+ /// If , always uses the name of the member, the same as if ToString() was called.
+ /// The string representation of the value
+ public static string ToStringFast(this global::Something.Blah.ShortName value, bool useMetadataAttributes)
+ => value.ToStringFast();
+
+ ///
+ /// Determines whether one or more bit fields are set in the current instance.
+ /// Equivalent to calling on .
+ ///
+ /// The value of the instance to investigate
+ /// The flag to check for
+ /// if the fields set in the flag are also set in the current instance; otherwise .
+ /// If the underlying value of is zero, the method returns true.
+ /// This is consistent with the behaviour of
+ public static bool HasFlagFast(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName flag)
+ => flag == 0 ? true : (value & flag) == flag;
+
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// Cast a value of to the underlying type (int).
+ /// This is mainly a convenience method.
+ ///
+ /// The value of cast to the underlying type.
+ public static int AsUnderlyingType(this global::Something.Blah.ShortName value)
+ {
+ return (int) value;
+ }
+
+ // C#14 Extension member syntax
+ extension(global::Something.Blah.ShortName)
+ {
+
+ ///
+ /// Returns a boolean telling whether the given enum value exists in the enumeration.
+ ///
+ /// The value to check if it's defined
+ /// if the value exists in the enumeration, otherwise
+ public static bool IsDefined(global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => true,
+ global::Something.Blah.ShortName.First => true,
+ global::Something.Blah.ShortName.Second => true,
+ global::Something.Blah.ShortName.Odd => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration.
+ ///
+ /// The name to check if it's defined
+ /// if a member with the name exists in the enumeration, otherwise
+ public static bool IsDefined(string name)
+ => name switch
+ {
+ nameof(global::Something.Blah.ShortName.None) => true,
+ nameof(global::Something.Blah.ShortName.First) => true,
+ nameof(global::Something.Blah.ShortName.Second) => true,
+ nameof(global::Something.Blah.ShortName.Odd) => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or if a member decorated with
+ /// with the required name exists.
+ ///
+ /// The name to check if it's defined
+ /// If ,
+ /// considers the value of
+ /// instead of the member name, otherwise ignores them
+ /// if a member with the name exists in the enumeration, or a member is decorated
+ /// with a [Display] attribute with the name, otherwise
+ public static bool IsDefined(string name, bool allowMatchingMetadataAttribute)
+ => IsDefined(name);
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration
+ ///
+ /// The name to check if it's defined
+ /// if a member with the name exists in the enumeration, otherwise
+ public static bool IsDefined(in global::System.ReadOnlySpan name)
+ => name switch
+ {
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.None)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.First)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Second)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Odd)), global::System.StringComparison.Ordinal) => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or optionally if a member decorated with
+ /// exists. Slower then the overload, but doesn't allocate memory./>
+ ///
+ /// The name to check if it's defined
+ /// If , considers the value of metadata attributes,otherwise ignores them
+ /// if a member with the name exists in the enumeration, or a member is decorated
+ /// with a [Display] attribute with the name, otherwise
+ public static bool IsDefined(in global::System.ReadOnlySpan name, bool allowMatchingMetadataAttribute)
+ => IsDefined(name);
+#endif
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name)
+ => TryParse(name, out var value, new global::NetEscapades.EnumGenerators.EnumParseOptions()) ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal))
+ ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in metadata attributes such as
+ /// [Display] attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute)) ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ => TryParse(
+ name,
+ out var value,
+ options) ? value : ThrowValueNotFound(name);
+
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
+#endif
+ private static global::Something.Blah.ShortName ThrowValueNotFound(string? name)
+ => throw new global::System.ArgumentException($"Requested value '{name}' was not found.");
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value)
+ => TryParse(name, out value, new global::NetEscapades.EnumGenerators.EnumParseOptions());
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase)
+ => TryParse(name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal));
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If ,
+ /// considers the value included in attribute
+ /// when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute));
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ {
+ switch (name)
+ {
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.None), options.ComparisonType):
+ value = global::Something.Blah.ShortName.None;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.First), options.ComparisonType):
+ value = global::Something.Blah.ShortName.First;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.Second), options.ComparisonType):
+ value = global::Something.Blah.ShortName.Second;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.Odd), options.ComparisonType):
+ value = global::Something.Blah.ShortName.Odd;
+ return true;
+ case string s when options.EnableNumberParsing && int.TryParse(name, out var val):
+ value = (global::Something.Blah.ShortName)val;
+ return true;
+ default:
+ value = default;
+ return false;
+ }
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions())
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal))
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute))
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, disable number parsing in the parameter.
+
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ => TryParse(
+ name,
+ out var value,
+ options) ? value : ThrowValueNotFound(name);
+
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
+#endif
+ private static global::Something.Blah.ShortName ThrowValueNotFound(in global::System.ReadOnlySpan name)
+#if NET6_0_OR_GREATER
+ => throw new global::System.ArgumentException($"Requested value '{name}' was not found.");
+#else
+ => throw new global::System.ArgumentException($"Requested value '{name.ToString()}' was not found.");
+#endif
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName value)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions());
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal));
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName result,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out result,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute));
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, disable number parsing in the parameter.
+
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName result,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ {
+ switch (name)
+ {
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.None)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.None;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.First)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.First;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Second)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.Second;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Odd)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.Odd;
+ return true;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ case global::System.ReadOnlySpan current when options.EnableNumberParsing && int.TryParse(name, out var numericResult):
+#else
+ // TryParse with ReadOnlySpan is not available, so we have to call ToString()
+ case global::System.ReadOnlySpan current when options.EnableNumberParsing && int.TryParse(name.ToString(), out var numericResult):
+#endif
+ result = (global::Something.Blah.ShortName)numericResult;
+ return true;
+ default:
+ result = default;
+ return false;
+ }
+ }
+#endif
+
+ ///
+ /// Retrieves an array of the values of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the values defined in
+ public static global::Something.Blah.ShortName[] GetValues()
+ => new[]
+ {
+ global::Something.Blah.ShortName.None,
+ global::Something.Blah.ShortName.First,
+ global::Something.Blah.ShortName.Second,
+ global::Something.Blah.ShortName.Odd,
+ };
+
+ ///
+ /// Retrieves an array of the underlying-values of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the underlying-values defined in
+ public static int[] GetValuesAsUnderlyingType()
+ => new[]
+ {
+ (int) global::Something.Blah.ShortName.None,
+ (int) global::Something.Blah.ShortName.First,
+ (int) global::Something.Blah.ShortName.Second,
+ (int) global::Something.Blah.ShortName.Odd,
+ };
+
+ ///
+ /// Retrieves an array of the names of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the names of the members defined in
+ public static string[] GetNames()
+ => new[]
+ {
+ nameof(global::Something.Blah.ShortName.None),
+ nameof(global::Something.Blah.ShortName.First),
+ nameof(global::Something.Blah.ShortName.Second),
+ nameof(global::Something.Blah.ShortName.Odd),
+ };
+ }
+ }
+#pragma warning restore CS0612 // Ignore usages of obsolete members or enums
+#pragma warning restore CS0618 // Ignore usages of obsolete members or enums
+}
\ No newline at end of file
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly_csharp14IsSupported=False.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly_csharp14IsSupported=False.verified.txt
index 39a725f..3f5cafe 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly_csharp14IsSupported=False.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly_csharp14IsSupported=False.verified.txt
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// This code was generated by the NetEscapades.EnumGenerators source generator
//
@@ -25,6 +25,11 @@ namespace Something.Blah
///
public const int Length = 2;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Something.Blah.ShortName All = global::Something.Blah.ShortName.First | global::Something.Blah.ShortName.Second;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -100,6 +105,48 @@ namespace Something.Blah
public static bool HasFlagFast(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 1;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::Something.Blah.ShortName value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::Something.Blah.ShortName.Second) == global::Something.Blah.ShortName.Second)
+ buffer[count++] = global::Something.Blah.ShortName.Second;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly_csharp14IsSupported=True.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly_csharp14IsSupported=True.verified.txt
index 215c19c..fac82ea 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly_csharp14IsSupported=True.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly_csharp14IsSupported=True.verified.txt
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// This code was generated by the NetEscapades.EnumGenerators source generator
//
@@ -25,6 +25,11 @@ namespace Something.Blah
///
public const int Length = 2;
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Something.Blah.ShortName All = global::Something.Blah.ShortName.First | global::Something.Blah.ShortName.Second;
+
///
/// Returns the string representation of the value.
/// Directly equivalent to calling ToString() on .
@@ -100,6 +105,48 @@ namespace Something.Blah
public static bool HasFlagFast(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName flag)
=> flag == 0 ? true : (value & flag) == flag;
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 1;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::Something.Blah.ShortName value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::Something.Blah.ShortName.Second) == global::Something.Blah.ShortName.Second)
+ buffer[count++] = global::Something.Blah.ShortName.Second;
+ return true;
+ }
+#endif
+
///
/// Cast a value of to the underlying type (int).
/// This is mainly a convenience method.
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesTryGetFlagsWithCleanCompositeMember_csharp14IsSupported=False.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesTryGetFlagsWithCleanCompositeMember_csharp14IsSupported=False.verified.txt
new file mode 100644
index 0000000..ca11283
--- /dev/null
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesTryGetFlagsWithCleanCompositeMember_csharp14IsSupported=False.verified.txt
@@ -0,0 +1,898 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by the NetEscapades.EnumGenerators source generator
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#nullable enable
+
+namespace Something.Blah
+{
+#pragma warning disable CS0612 // Ignore usages of obsolete members or enums
+#pragma warning disable CS0618 // Ignore usages of obsolete members or enums
+ ///
+ /// Extension methods for
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("NetEscapades.EnumGenerators", "FIXED_VERSION")]
+ public static partial class ShortName
+ {
+ ///
+ /// The number of members in the enum.
+ /// This is a non-distinct count of defined names.
+ ///
+ public const int Length = 4;
+
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Something.Blah.ShortName All = global::Something.Blah.ShortName.None | global::Something.Blah.ShortName.First | global::Something.Blah.ShortName.Second | global::Something.Blah.ShortName.Both;
+
+ ///
+ /// Returns the string representation of the value.
+ /// Directly equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The string representation of the value, the same as that returned by ToString()
+ public static string ToStringFast(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => nameof(global::Something.Blah.ShortName.None),
+ global::Something.Blah.ShortName.First => nameof(global::Something.Blah.ShortName.First),
+ global::Something.Blah.ShortName.Second => nameof(global::Something.Blah.ShortName.Second),
+ global::Something.Blah.ShortName.Both => nameof(global::Something.Blah.ShortName.Both),
+ _ => value.ToString(),
+ };
+
+ ///
+ /// Returns the string representation of the value.
+ /// Directly equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The options to use when serializing the enum
+ /// The string representation of the value, using the provided options.
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static string ToStringFast(this global::Something.Blah.ShortName value, global::NetEscapades.EnumGenerators.SerializationOptions options)
+ => options.Transform switch
+ {
+ global::NetEscapades.EnumGenerators.SerializationTransform.LowerInvariant => value.ToStringFastLowerInvariant(),
+ global::NetEscapades.EnumGenerators.SerializationTransform.UpperInvariant => value.ToStringFastUpperInvariant(),
+ _ => value.ToStringFast(),
+ };
+
+ private static string ToStringFastLowerInvariant(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => "none",
+ global::Something.Blah.ShortName.First => "first",
+ global::Something.Blah.ShortName.Second => "second",
+ global::Something.Blah.ShortName.Both => "both",
+ _ => value.ToString().ToLowerInvariant(),
+ };
+
+ private static string ToStringFastUpperInvariant(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => "NONE",
+ global::Something.Blah.ShortName.First => "FIRST",
+ global::Something.Blah.ShortName.Second => "SECOND",
+ global::Something.Blah.ShortName.Both => "BOTH",
+ _ => value.ToString().ToUpperInvariant(),
+ };
+
+ ///
+ /// Returns the string representation of the value.
+ /// If the member is decorated with the attribute
+ /// then that value is returned. Otherwise returns uses the name of the member,
+ /// equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// If uses the value provided in the
+ /// attribute as the string representation of the member.
+ /// If , always uses the name of the member, the same as if ToString() was called.
+ /// The string representation of the value
+ public static string ToStringFast(this global::Something.Blah.ShortName value, bool useMetadataAttributes)
+ => value.ToStringFast();
+
+ ///
+ /// Determines whether one or more bit fields are set in the current instance.
+ /// Equivalent to calling on .
+ ///
+ /// The value of the instance to investigate
+ /// The flag to check for
+ /// if the fields set in the flag are also set in the current instance; otherwise .
+ /// If the underlying value of is zero, the method returns true.
+ /// This is consistent with the behaviour of
+ public static bool HasFlagFast(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName flag)
+ => flag == 0 ? true : (value & flag) == flag;
+
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 2;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::Something.Blah.ShortName value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::Something.Blah.ShortName.First) == global::Something.Blah.ShortName.First)
+ buffer[count++] = global::Something.Blah.ShortName.First;
+ if ((value & global::Something.Blah.ShortName.Second) == global::Something.Blah.ShortName.Second)
+ buffer[count++] = global::Something.Blah.ShortName.Second;
+ return true;
+ }
+#endif
+
+ ///
+ /// Cast a value of to the underlying type (int).
+ /// This is mainly a convenience method.
+ ///
+ /// The value of cast to the underlying type.
+ public static int AsUnderlyingType(this global::Something.Blah.ShortName value)
+ {
+ return (int) value;
+ }
+
+ ///
+ /// Returns a boolean telling whether the given enum value exists in the enumeration.
+ ///
+ /// The value to check if it's defined
+ /// if the value exists in the enumeration, otherwise
+ public static bool IsDefined(global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => true,
+ global::Something.Blah.ShortName.First => true,
+ global::Something.Blah.ShortName.Second => true,
+ global::Something.Blah.ShortName.Both => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration.
+ ///
+ /// The name to check if it's defined
+ /// if a member with the name exists in the enumeration, otherwise
+ public static bool IsDefined(string name)
+ => name switch
+ {
+ nameof(global::Something.Blah.ShortName.None) => true,
+ nameof(global::Something.Blah.ShortName.First) => true,
+ nameof(global::Something.Blah.ShortName.Second) => true,
+ nameof(global::Something.Blah.ShortName.Both) => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or if a member decorated with
+ /// with the required name exists.
+ ///
+ /// The name to check if it's defined
+ /// If ,
+ /// considers the value of
+ /// instead of the member name, otherwise ignores them
+ /// if a member with the name exists in the enumeration, or a member is decorated
+ /// with a [Display] attribute with the name, otherwise
+ public static bool IsDefined(string name, bool allowMatchingMetadataAttribute)
+ => IsDefined(name);
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration
+ ///
+ /// The name to check if it's defined
+ /// if a member with the name exists in the enumeration, otherwise
+ public static bool IsDefined(in global::System.ReadOnlySpan name)
+ => name switch
+ {
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.None)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.First)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Second)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Both)), global::System.StringComparison.Ordinal) => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or optionally if a member decorated with
+ /// exists. Slower then the overload, but doesn't allocate memory./>
+ ///
+ /// The name to check if it's defined
+ /// If , considers the value of metadata attributes,otherwise ignores them
+ /// if a member with the name exists in the enumeration, or a member is decorated
+ /// with a [Display] attribute with the name, otherwise
+ public static bool IsDefined(in global::System.ReadOnlySpan name, bool allowMatchingMetadataAttribute)
+ => IsDefined(name);
+#endif
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name)
+ => TryParse(name, out var value, new global::NetEscapades.EnumGenerators.EnumParseOptions()) ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal))
+ ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in metadata attributes such as
+ /// [Display] attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute)) ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ => TryParse(
+ name,
+ out var value,
+ options) ? value : ThrowValueNotFound(name);
+
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
+#endif
+ private static global::Something.Blah.ShortName ThrowValueNotFound(string? name)
+ => throw new global::System.ArgumentException($"Requested value '{name}' was not found.");
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value)
+ => TryParse(name, out value, new global::NetEscapades.EnumGenerators.EnumParseOptions());
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase)
+ => TryParse(name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal));
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If ,
+ /// considers the value included in attribute
+ /// when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute));
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ {
+ switch (name)
+ {
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.None), options.ComparisonType):
+ value = global::Something.Blah.ShortName.None;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.First), options.ComparisonType):
+ value = global::Something.Blah.ShortName.First;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.Second), options.ComparisonType):
+ value = global::Something.Blah.ShortName.Second;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.Both), options.ComparisonType):
+ value = global::Something.Blah.ShortName.Both;
+ return true;
+ case string s when options.EnableNumberParsing && int.TryParse(name, out var val):
+ value = (global::Something.Blah.ShortName)val;
+ return true;
+ default:
+ value = default;
+ return false;
+ }
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions())
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal))
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute))
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, disable number parsing in the parameter.
+
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ => TryParse(
+ name,
+ out var value,
+ options) ? value : ThrowValueNotFound(name);
+
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
+#endif
+ private static global::Something.Blah.ShortName ThrowValueNotFound(in global::System.ReadOnlySpan name)
+#if NET6_0_OR_GREATER
+ => throw new global::System.ArgumentException($"Requested value '{name}' was not found.");
+#else
+ => throw new global::System.ArgumentException($"Requested value '{name.ToString()}' was not found.");
+#endif
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName value)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions());
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal));
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName result,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out result,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute));
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, disable number parsing in the parameter.
+
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName result,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ {
+ switch (name)
+ {
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.None)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.None;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.First)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.First;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Second)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.Second;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Both)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.Both;
+ return true;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ case global::System.ReadOnlySpan current when options.EnableNumberParsing && int.TryParse(name, out var numericResult):
+#else
+ // TryParse with ReadOnlySpan is not available, so we have to call ToString()
+ case global::System.ReadOnlySpan current when options.EnableNumberParsing && int.TryParse(name.ToString(), out var numericResult):
+#endif
+ result = (global::Something.Blah.ShortName)numericResult;
+ return true;
+ default:
+ result = default;
+ return false;
+ }
+ }
+#endif
+
+ ///
+ /// Retrieves an array of the values of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the values defined in
+ public static global::Something.Blah.ShortName[] GetValues()
+ => new[]
+ {
+ global::Something.Blah.ShortName.None,
+ global::Something.Blah.ShortName.First,
+ global::Something.Blah.ShortName.Second,
+ global::Something.Blah.ShortName.Both,
+ };
+
+ ///
+ /// Retrieves an array of the underlying-values of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the underlying-values defined in
+ public static int[] GetValuesAsUnderlyingType()
+ => new[]
+ {
+ (int) global::Something.Blah.ShortName.None,
+ (int) global::Something.Blah.ShortName.First,
+ (int) global::Something.Blah.ShortName.Second,
+ (int) global::Something.Blah.ShortName.Both,
+ };
+
+ ///
+ /// Retrieves an array of the names of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the names of the members defined in
+ public static string[] GetNames()
+ => new[]
+ {
+ nameof(global::Something.Blah.ShortName.None),
+ nameof(global::Something.Blah.ShortName.First),
+ nameof(global::Something.Blah.ShortName.Second),
+ nameof(global::Something.Blah.ShortName.Both),
+ };
+ }
+#pragma warning restore CS0612 // Ignore usages of obsolete members or enums
+#pragma warning restore CS0618 // Ignore usages of obsolete members or enums
+}
\ No newline at end of file
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesTryGetFlagsWithCleanCompositeMember_csharp14IsSupported=True.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesTryGetFlagsWithCleanCompositeMember_csharp14IsSupported=True.verified.txt
new file mode 100644
index 0000000..ebb6bc0
--- /dev/null
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesTryGetFlagsWithCleanCompositeMember_csharp14IsSupported=True.verified.txt
@@ -0,0 +1,903 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by the NetEscapades.EnumGenerators source generator
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#nullable enable
+
+namespace Something.Blah
+{
+#pragma warning disable CS0612 // Ignore usages of obsolete members or enums
+#pragma warning disable CS0618 // Ignore usages of obsolete members or enums
+ ///
+ /// Extension methods for
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("NetEscapades.EnumGenerators", "FIXED_VERSION")]
+ public static partial class ShortName
+ {
+ ///
+ /// The number of members in the enum.
+ /// This is a non-distinct count of defined names.
+ ///
+ public const int Length = 4;
+
+ ///
+ /// A bitwise OR combination of all defined values in the enum.
+ ///
+ public const global::Something.Blah.ShortName All = global::Something.Blah.ShortName.None | global::Something.Blah.ShortName.First | global::Something.Blah.ShortName.Second | global::Something.Blah.ShortName.Both;
+
+ ///
+ /// Returns the string representation of the value.
+ /// Directly equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The string representation of the value, the same as that returned by ToString()
+ public static string ToStringFast(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => nameof(global::Something.Blah.ShortName.None),
+ global::Something.Blah.ShortName.First => nameof(global::Something.Blah.ShortName.First),
+ global::Something.Blah.ShortName.Second => nameof(global::Something.Blah.ShortName.Second),
+ global::Something.Blah.ShortName.Both => nameof(global::Something.Blah.ShortName.Both),
+ _ => value.ToString(),
+ };
+
+ ///
+ /// Returns the string representation of the value.
+ /// Directly equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The options to use when serializing the enum
+ /// The string representation of the value, using the provided options.
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static string ToStringFast(this global::Something.Blah.ShortName value, global::NetEscapades.EnumGenerators.SerializationOptions options)
+ => options.Transform switch
+ {
+ global::NetEscapades.EnumGenerators.SerializationTransform.LowerInvariant => value.ToStringFastLowerInvariant(),
+ global::NetEscapades.EnumGenerators.SerializationTransform.UpperInvariant => value.ToStringFastUpperInvariant(),
+ _ => value.ToStringFast(),
+ };
+
+ private static string ToStringFastLowerInvariant(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => "none",
+ global::Something.Blah.ShortName.First => "first",
+ global::Something.Blah.ShortName.Second => "second",
+ global::Something.Blah.ShortName.Both => "both",
+ _ => value.ToString().ToLowerInvariant(),
+ };
+
+ private static string ToStringFastUpperInvariant(this global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => "NONE",
+ global::Something.Blah.ShortName.First => "FIRST",
+ global::Something.Blah.ShortName.Second => "SECOND",
+ global::Something.Blah.ShortName.Both => "BOTH",
+ _ => value.ToString().ToUpperInvariant(),
+ };
+
+ ///
+ /// Returns the string representation of the value.
+ /// If the member is decorated with the attribute
+ /// then that value is returned. Otherwise returns uses the name of the member,
+ /// equivalent to calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// If uses the value provided in the
+ /// attribute as the string representation of the member.
+ /// If , always uses the name of the member, the same as if ToString() was called.
+ /// The string representation of the value
+ public static string ToStringFast(this global::Something.Blah.ShortName value, bool useMetadataAttributes)
+ => value.ToStringFast();
+
+ ///
+ /// Determines whether one or more bit fields are set in the current instance.
+ /// Equivalent to calling on .
+ ///
+ /// The value of the instance to investigate
+ /// The flag to check for
+ /// if the fields set in the flag are also set in the current instance; otherwise .
+ /// If the underlying value of is zero, the method returns true.
+ /// This is consistent with the behaviour of
+ public static bool HasFlagFast(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName flag)
+ => flag == 0 ? true : (value & flag) == flag;
+
+ ///
+ /// Determines whether any of the bit fields are set in the current instance.
+ ///
+ /// The value of the instance to investigate
+ /// The flags to check for
+ /// if any of the fields set in are
+ /// also set in ; otherwise .
+ /// If the underlying value of is zero, the method
+ /// always returns , consistent with the behaviour of .
+ public static bool HasAnyFlags(this global::Something.Blah.ShortName value, global::Something.Blah.ShortName otherFlags)
+ => otherFlags == 0 ? true : (value & otherFlags) != 0;
+
+ ///
+ /// The number of distinct single-bit flag members defined in the enum.
+ /// This is the buffer size required by .
+ ///
+ public const int DistinctFlagCount = 2;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Writes each defined single-bit flag set in into .
+ /// Composite members (e.g. a member defined as A | B) are decomposed into their constituent single-bit flags.
+ /// The zero/None value never appears in the output.
+ ///
+ /// The value to decompose into individual flags.
+ /// The buffer to write the flags into. Must be at least elements.
+ /// The number of flags written to . Set to 0 if the method returns .
+ /// if the buffer was large enough; if it was smaller than .
+ public static bool TryGetFlags(this global::Something.Blah.ShortName value, global::System.Span buffer, out int count)
+ {
+ if (buffer.Length < DistinctFlagCount)
+ {
+ count = 0;
+ return false;
+ }
+ count = 0;
+ if ((value & global::Something.Blah.ShortName.First) == global::Something.Blah.ShortName.First)
+ buffer[count++] = global::Something.Blah.ShortName.First;
+ if ((value & global::Something.Blah.ShortName.Second) == global::Something.Blah.ShortName.Second)
+ buffer[count++] = global::Something.Blah.ShortName.Second;
+ return true;
+ }
+#endif
+
+ ///
+ /// Cast a value of to the underlying type (int).
+ /// This is mainly a convenience method.
+ ///
+ /// The value of cast to the underlying type.
+ public static int AsUnderlyingType(this global::Something.Blah.ShortName value)
+ {
+ return (int) value;
+ }
+
+ // C#14 Extension member syntax
+ extension(global::Something.Blah.ShortName)
+ {
+
+ ///
+ /// Returns a boolean telling whether the given enum value exists in the enumeration.
+ ///
+ /// The value to check if it's defined
+ /// if the value exists in the enumeration, otherwise
+ public static bool IsDefined(global::Something.Blah.ShortName value)
+ => value switch
+ {
+ global::Something.Blah.ShortName.None => true,
+ global::Something.Blah.ShortName.First => true,
+ global::Something.Blah.ShortName.Second => true,
+ global::Something.Blah.ShortName.Both => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration.
+ ///
+ /// The name to check if it's defined
+ /// if a member with the name exists in the enumeration, otherwise
+ public static bool IsDefined(string name)
+ => name switch
+ {
+ nameof(global::Something.Blah.ShortName.None) => true,
+ nameof(global::Something.Blah.ShortName.First) => true,
+ nameof(global::Something.Blah.ShortName.Second) => true,
+ nameof(global::Something.Blah.ShortName.Both) => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or if a member decorated with
+ /// with the required name exists.
+ ///
+ /// The name to check if it's defined
+ /// If ,
+ /// considers the value of
+ /// instead of the member name, otherwise ignores them
+ /// if a member with the name exists in the enumeration, or a member is decorated
+ /// with a [Display] attribute with the name, otherwise
+ public static bool IsDefined(string name, bool allowMatchingMetadataAttribute)
+ => IsDefined(name);
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration
+ ///
+ /// The name to check if it's defined
+ /// if a member with the name exists in the enumeration, otherwise
+ public static bool IsDefined(in global::System.ReadOnlySpan name)
+ => name switch
+ {
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.None)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.First)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Second)), global::System.StringComparison.Ordinal) => true,
+ global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Both)), global::System.StringComparison.Ordinal) => true,
+ _ => false,
+ };
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or optionally if a member decorated with
+ /// exists. Slower then the overload, but doesn't allocate memory./>
+ ///
+ /// The name to check if it's defined
+ /// If , considers the value of metadata attributes,otherwise ignores them
+ /// if a member with the name exists in the enumeration, or a member is decorated
+ /// with a [Display] attribute with the name, otherwise
+ public static bool IsDefined(in global::System.ReadOnlySpan name, bool allowMatchingMetadataAttribute)
+ => IsDefined(name);
+#endif
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name)
+ => TryParse(name, out var value, new global::NetEscapades.EnumGenerators.EnumParseOptions()) ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal))
+ ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in metadata attributes such as
+ /// [Display] attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute)) ? value : ThrowValueNotFound(name);
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static global::Something.Blah.ShortName Parse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ => TryParse(
+ name,
+ out var value,
+ options) ? value : ThrowValueNotFound(name);
+
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
+#endif
+ private static global::Something.Blah.ShortName ThrowValueNotFound(string? name)
+ => throw new global::System.ArgumentException($"Requested value '{name}' was not found.");
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value)
+ => TryParse(name, out value, new global::NetEscapades.EnumGenerators.EnumParseOptions());
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase)
+ => TryParse(name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal));
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If ,
+ /// considers the value included in attribute
+ /// when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute));
+
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out global::Something.Blah.ShortName value,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ {
+ switch (name)
+ {
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.None), options.ComparisonType):
+ value = global::Something.Blah.ShortName.None;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.First), options.ComparisonType):
+ value = global::Something.Blah.ShortName.First;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.Second), options.ComparisonType):
+ value = global::Something.Blah.ShortName.Second;
+ return true;
+ case string s when s.Equals(nameof(global::Something.Blah.ShortName.Both), options.ComparisonType):
+ value = global::Something.Blah.ShortName.Both;
+ return true;
+ case string s when options.EnableNumberParsing && int.TryParse(name, out var val):
+ value = (global::Something.Blah.ShortName)val;
+ return true;
+ default:
+ value = default;
+ return false;
+ }
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions())
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal))
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The case-sensitive string representation of the enumeration name or underlying value to convert
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// An object of type whose
+ /// value is represented by
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out var value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute))
+ ? value : ThrowValueNotFound(name);
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, disable number parsing in the parameter.
+
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+ public static global::Something.Blah.ShortName Parse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// Options that control how the string value should be parsed.
+ /// An object of type whose
+ /// value is represented by
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static global::Something.Blah.ShortName Parse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ => TryParse(
+ name,
+ out var value,
+ options) ? value : ThrowValueNotFound(name);
+
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.DoesNotReturn]
+#endif
+ private static global::Something.Blah.ShortName ThrowValueNotFound(in global::System.ReadOnlySpan name)
+#if NET6_0_OR_GREATER
+ => throw new global::System.ArgumentException($"Requested value '{name}' was not found.");
+#else
+ => throw new global::System.ArgumentException($"Requested value '{name.ToString()}' was not found.");
+#endif
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName value)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions());
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName value,
+ bool ignoreCase)
+ => TryParse(
+ name,
+ out value,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal));
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, call the
+ /// overload, and disable number parsing.
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the span representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The span representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// to read value in case insensitive mode; to read value in case sensitive mode.
+ /// If , considers the value included in
+ /// attribute when parsing, otherwise only considers the member names.
+ /// if the value parameter was converted successfully; otherwise, .
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName result,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ => TryParse(
+ name,
+ out result,
+ new global::NetEscapades.EnumGenerators.EnumParseOptions(
+ ignoreCase ? global::System.StringComparison.OrdinalIgnoreCase : global::System.StringComparison.Ordinal,
+ allowMatchingMetadataAttribute: allowMatchingMetadataAttribute));
+
+#if !NETCOREAPP2_1_OR_GREATER && !NETSTANDARD2_1_OR_GREATER && NETESCAPADES_ENUMGENERATORS_SYSTEM_MEMORY
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+ /// WARNING: This API will allocate a when
+ /// is not explicitly defined in when attempting to parse as a number.
+ /// To avoid this allocation, only call this overload when you know the value will exist.
+ /// Alternatively, disable number parsing in the parameter.
+
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+ public static bool TryParse(
+#else
+ ///
+ /// Converts the string representation of the name or numeric value of
+ /// an to the equivalent instance.
+ /// The return value indicates whether the conversion succeeded.
+ ///
+ /// The string representation of the enumeration name or underlying value to convert
+ /// When this method returns, contains an object of type
+ /// whose
+ /// value is represented by if the parse operation succeeds.
+ /// If the parse operation fails, contains the default value of the underlying type
+ /// of . This parameter is passed uninitialized.
+ /// Options that control how the string value should be parsed.
+ /// if the value parameter was converted successfully; otherwise, .
+#if !NETESCAPADES_ENUMGENERATORS_OMIT_OVERLOAD_PRIORITY
+ [global::System.Runtime.CompilerServices.OverloadResolutionPriority(1)]
+#endif
+
+ public static bool TryParse(
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in global::System.ReadOnlySpan name,
+ out global::Something.Blah.ShortName result,
+ global::NetEscapades.EnumGenerators.EnumParseOptions options)
+ {
+ switch (name)
+ {
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.None)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.None;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.First)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.First;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Second)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.Second;
+ return true;
+ case global::System.ReadOnlySpan current when global::System.MemoryExtensions.Equals(current, global::System.MemoryExtensions.AsSpan(nameof(global::Something.Blah.ShortName.Both)), options.ComparisonType):
+ result = global::Something.Blah.ShortName.Both;
+ return true;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ case global::System.ReadOnlySpan current when options.EnableNumberParsing && int.TryParse(name, out var numericResult):
+#else
+ // TryParse with ReadOnlySpan is not available, so we have to call ToString()
+ case global::System.ReadOnlySpan current when options.EnableNumberParsing && int.TryParse(name.ToString(), out var numericResult):
+#endif
+ result = (global::Something.Blah.ShortName)numericResult;
+ return true;
+ default:
+ result = default;
+ return false;
+ }
+ }
+#endif
+
+ ///
+ /// Retrieves an array of the values of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the values defined in
+ public static global::Something.Blah.ShortName[] GetValues()
+ => new[]
+ {
+ global::Something.Blah.ShortName.None,
+ global::Something.Blah.ShortName.First,
+ global::Something.Blah.ShortName.Second,
+ global::Something.Blah.ShortName.Both,
+ };
+
+ ///
+ /// Retrieves an array of the underlying-values of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the underlying-values defined in
+ public static int[] GetValuesAsUnderlyingType()
+ => new[]
+ {
+ (int) global::Something.Blah.ShortName.None,
+ (int) global::Something.Blah.ShortName.First,
+ (int) global::Something.Blah.ShortName.Second,
+ (int) global::Something.Blah.ShortName.Both,
+ };
+
+ ///
+ /// Retrieves an array of the names of the members defined in
+ /// .
+ /// Note that this returns a new array with every invocation, so
+ /// should be cached if appropriate.
+ ///
+ /// An array of the names of the members defined in
+ public static string[] GetNames()
+ => new[]
+ {
+ nameof(global::Something.Blah.ShortName.None),
+ nameof(global::Something.Blah.ShortName.First),
+ nameof(global::Something.Blah.ShortName.Second),
+ nameof(global::Something.Blah.ShortName.Both),
+ };
+ }
+ }
+#pragma warning restore CS0612 // Ignore usages of obsolete members or enums
+#pragma warning restore CS0618 // Ignore usages of obsolete members or enums
+}
\ No newline at end of file
diff --git a/tests/NetEscapades.EnumGenerators.Tests/SourceGenerationHelperSnapshotTests.cs b/tests/NetEscapades.EnumGenerators.Tests/SourceGenerationHelperSnapshotTests.cs
index d5ac5c9..f86f201 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/SourceGenerationHelperSnapshotTests.cs
+++ b/tests/NetEscapades.EnumGenerators.Tests/SourceGenerationHelperSnapshotTests.cs
@@ -116,6 +116,79 @@ public Task GeneratesFlagsEnumCorrectly(bool csharp14IsSupported)
.UseParameters(csharp14IsSupported);
}
+ [Theory]
+ [CombinatorialData]
+ public Task DoesNotGenerateTryGetFlagsWhenMemberHasUndefinedBits(bool csharp14IsSupported)
+ {
+ // A member whose value contains a bit not corresponding to any single-bit flag disqualifies emission.
+ // Here Odd=5 = 1|4, but 4 is not defined as a single-bit flag, so no TryGetFlags is generated.
+ var value = new EnumToGenerate(
+ "ShortName",
+ "Something.Blah",
+ "Something.Blah.ShortName",
+ "int",
+ isPublic: true,
+ new List<(string, EnumValueOption)>
+ {
+ ("None", EnumValueOption.CreateWithoutAttributes(0)),
+ ("First", EnumValueOption.CreateWithoutAttributes(1)),
+ ("Second", EnumValueOption.CreateWithoutAttributes(2)),
+ ("Odd", EnumValueOption.CreateWithoutAttributes(5)),
+ },
+ hasFlags: true,
+ metadataSource: null);
+
+ var result = SourceGenerationHelper.GenerateExtensionClass(
+ value,
+ csharp14IsSupported,
+ useCollectionExpressions: false,
+ DefaultMetadataSource,
+ hasRuntimeDependencies: true,
+ forceInternal: false,
+ hasOverloadResolutionPriority: true).Content;
+
+ return Verifier.Verify(result)
+ .ScrubExpectedChanges()
+ .UseDirectory("Snapshots")
+ .UseParameters(csharp14IsSupported);
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public Task GeneratesTryGetFlagsWithCleanCompositeMember(bool csharp14IsSupported)
+ {
+ // A composite member that's a clean combination of single-bit flags is fine; TryGetFlags is emitted.
+ var value = new EnumToGenerate(
+ "ShortName",
+ "Something.Blah",
+ "Something.Blah.ShortName",
+ "int",
+ isPublic: true,
+ new List<(string, EnumValueOption)>
+ {
+ ("None", EnumValueOption.CreateWithoutAttributes(0)),
+ ("First", EnumValueOption.CreateWithoutAttributes(1)),
+ ("Second", EnumValueOption.CreateWithoutAttributes(2)),
+ ("Both", EnumValueOption.CreateWithoutAttributes(3)),
+ },
+ hasFlags: true,
+ metadataSource: null);
+
+ var result = SourceGenerationHelper.GenerateExtensionClass(
+ value,
+ csharp14IsSupported,
+ useCollectionExpressions: false,
+ DefaultMetadataSource,
+ hasRuntimeDependencies: true,
+ forceInternal: false,
+ hasOverloadResolutionPriority: true).Content;
+
+ return Verifier.Verify(result)
+ .ScrubExpectedChanges()
+ .UseDirectory("Snapshots")
+ .UseParameters(csharp14IsSupported);
+ }
+
[Fact]
public Task GeneratesForcedInternalEnumCorrectly()
{