diff --git a/README.md b/README.md
index 3b45b9a..7ea1cba 100644
--- a/README.md
+++ b/README.md
@@ -148,6 +148,13 @@ public static partial class MyEnumExtensions
}
```
+If you create a "Flags" `enum` by decorating it with the `[Flags]` attribute, an additional method is created, which provides a bitwise alternative to :
+
+```csharp
+public static bool HasFlagFast(this MyEnum value, MyEnum flag)
+ => flag == 0 ? true : (value & flag) == flag;
+```
+
You can override the name of the extension class by setting `ExtensionClassName` in the attribute and/or the namespace of the class by setting `ExtensionClassNamespace`. By default, the class will be public if the enum is public, otherwise it will be internal.
## Embedding the attributes in your project
diff --git a/src/NetEscapades.EnumGenerators/EnumGenerator.cs b/src/NetEscapades.EnumGenerators/EnumGenerator.cs
index 0efd6cf..1569890 100644
--- a/src/NetEscapades.EnumGenerators/EnumGenerator.cs
+++ b/src/NetEscapades.EnumGenerators/EnumGenerator.cs
@@ -10,7 +10,7 @@ public class EnumGenerator : IIncrementalGenerator
{
private const string DisplayAttribute = "System.ComponentModel.DataAnnotations.DisplayAttribute";
private const string EnumExtensionsAttribute = "NetEscapades.EnumGenerators.EnumExtensionsAttribute";
- private const string HasFlagsAttribute = "System.HasFlagsAttribute";
+ private const string FlagsAttribute = "System.FlagsAttribute";
public void Initialize(IncrementalGeneratorInitializationContext context)
{
@@ -55,8 +55,9 @@ static void Execute(in EnumToGenerate? enumToGenerate, SourceProductionContext c
foreach (AttributeData attributeData in enumSymbol.GetAttributes())
{
- if (attributeData.AttributeClass?.Name == "HasFlagsAttribute" &&
- attributeData.AttributeClass.ToDisplayString() == HasFlagsAttribute)
+ if ((attributeData.AttributeClass?.Name == "FlagsAttribute" ||
+ attributeData.AttributeClass?.Name == "Flags") &&
+ attributeData.AttributeClass.ToDisplayString() == FlagsAttribute)
{
hasFlags = true;
continue;
diff --git a/src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs b/src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs
index e547835..0a94077 100644
--- a/src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs
+++ b/src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs
@@ -110,17 +110,15 @@ public static string ToStringFast(this ").Append(enumToGenerate.FullyQualifiedNa
///
/// Determines whether one or more bit fields are set in the current instance.
- /// Equivalent to calling value.HasFlag(flag)
+ /// Equivalent to calling on .
///
/// The value of the instance to investiage
/// The flag to check for
/// true if the fields set in the flag are also set in the current instance; otherwise false .
- public static bool HasFlag(this ").Append(enumToGenerate.FullyQualifiedName).Append(@" value, ").Append(enumToGenerate.FullyQualifiedName).Append(@" flag)
- => value switch
- {
- 0 => flag.Equals(0),
- _ => (value & flag) != 0,
- };");
+ /// If the underlying value of is zero, the method returns true.
+ /// This is consistent with the behaviour of
+ public static bool HasFlagFast(this ").Append(enumToGenerate.FullyQualifiedName).Append(@" value, ").Append(enumToGenerate.FullyQualifiedName).Append(@" flag)
+ => flag == 0 ? true : (value & flag) == flag;");
}
sb.Append(@"
diff --git a/tests/NetEscapades.EnumGenerators.IntegrationTests/FlagsEnumExtensionsTests.cs b/tests/NetEscapades.EnumGenerators.IntegrationTests/FlagsEnumExtensionsTests.cs
index e2cec8e..a1b870d 100644
--- a/tests/NetEscapades.EnumGenerators.IntegrationTests/FlagsEnumExtensionsTests.cs
+++ b/tests/NetEscapades.EnumGenerators.IntegrationTests/FlagsEnumExtensionsTests.cs
@@ -1,5 +1,7 @@
using FluentAssertions;
using System;
+using System.Collections.Generic;
+using System.Linq;
using Xunit;
namespace NetEscapades.EnumGenerators.IntegrationTests;
@@ -44,6 +46,12 @@ protected override bool TryParse(in ReadOnlySpan name, out FlagsEnum parse
=> FlagsEnumExtensions.TryParse(name, out parsed, ignoreCase);
#endif
+ ///
+ ///
+ ///
+ ///
+ /// If the underlying value of is zero, the method returns true.
+ /// This is consistent with the behaviour of
[Theory]
[MemberData(nameof(ValidEnumValues))]
public void GeneratesToStringFast(FlagsEnum value) => GeneratesToStringFastTest(value);
@@ -62,16 +70,29 @@ protected override bool TryParse(in ReadOnlySpan name, out FlagsEnum parse
public void GeneratesIsDefinedUsingNameAsSpan(string name) => GeneratesIsDefinedTest(name.AsSpan(), allowMatchingMetadataAttribute: false);
#endif
+ public static IEnumerable AllFlags()
+ {
+ var values = new[]
+ {
+ FlagsEnum.First,
+ FlagsEnum.Second,
+ FlagsEnum.Third,
+ FlagsEnum.ThirdAndFourth,
+ FlagsEnum.First | FlagsEnum.Second,
+ (FlagsEnum)65,
+ (FlagsEnum)0,
+ };
+
+ return from v1 in values
+ from v2 in values
+ select new object[] { v1, v2 };
+ }
+
[Theory]
- [InlineData(FlagsEnum.First)]
- [InlineData(FlagsEnum.Second)]
- [InlineData(FlagsEnum.First | FlagsEnum.Second)]
- [InlineData(FlagsEnum.Third)]
- [InlineData((FlagsEnum)65)]
- public void HasFlags(FlagsEnum value)
+ [MemberData(nameof(AllFlags))]
+ public void HasFlags(FlagsEnum value, FlagsEnum flag)
{
- var flag = FlagsEnum.Second;
- var isDefined = value.HasFlag(flag);
+ var isDefined = value.HasFlagFast(flag);
isDefined.Should().Be(value.HasFlag(flag));
}
diff --git a/tests/NetEscapades.EnumGenerators.Tests/EnumGeneratorTests.cs b/tests/NetEscapades.EnumGenerators.Tests/EnumGeneratorTests.cs
index 149cc86..32cadaa 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/EnumGeneratorTests.cs
+++ b/tests/NetEscapades.EnumGenerators.Tests/EnumGeneratorTests.cs
@@ -188,4 +188,36 @@ public enum MyEnum
Assert.Empty(diagnostics);
return Verifier.Verify(output).UseDirectory("Snapshots");
}
+
+ [Theory]
+ [InlineData("", "System.Flags")]
+ [InlineData("", "System.FlagsAttribute")]
+ [InlineData("using System;", "FlagsAttribute")]
+ [InlineData("using System;", "Flags")]
+ public Task CanGenerateEnumExtensionsForFlagsEnum(string usings, string attribute)
+ {
+ string input = $$"""
+ using NetEscapades.EnumGenerators;
+ {{usings}}
+
+ namespace MyTestNameSpace
+ {
+ [EnumExtensions, {{attribute}}]
+ public enum MyEnum
+ {
+ First = 1,
+ Second = 2,
+ Third = 4,
+ }
+ }
+ """;
+
+ var (diagnostics, output) = TestHelpers.GetGeneratedOutput(input);
+
+ Assert.Empty(diagnostics);
+ return Verifier.Verify(output)
+ .UseTextForParameters("Params")
+ .DisableRequireUniquePrefix()
+ .UseDirectory("Snapshots");
+ }
}
\ No newline at end of file
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateEnumExtensionsForFlagsEnum_Params.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateEnumExtensionsForFlagsEnum_Params.verified.txt
new file mode 100644
index 0000000..20f14a5
--- /dev/null
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/EnumGeneratorTests.CanGenerateEnumExtensionsForFlagsEnum_Params.verified.txt
@@ -0,0 +1,384 @@
+//------------------------------------------------------------------------------
+//
+// 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
+#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0
+using System;
+#endif
+
+namespace MyTestNameSpace
+{
+ ///
+ /// Extension methods for
+ ///
+ public static partial class MyEnumExtensions
+ {
+ ///
+ /// The number of members in the enum.
+ /// This is a non-distinct count of defined names.
+ ///
+ public const int Length = 3;
+
+ ///
+ /// Returns the string representation of the value.
+ /// If the attribute is decorated with a , then
+ /// uses the provided value. Otherwise uses the name of the member, equivalent to
+ /// calling ToString() on .
+ ///
+ /// The value to retrieve the string value for
+ /// The string representation of the value
+ public static string ToStringFast(this MyTestNameSpace.MyEnum value)
+ => value switch
+ {
+ MyTestNameSpace.MyEnum.First => nameof(MyTestNameSpace.MyEnum.First),
+ MyTestNameSpace.MyEnum.Second => nameof(MyTestNameSpace.MyEnum.Second),
+ MyTestNameSpace.MyEnum.Third => nameof(MyTestNameSpace.MyEnum.Third),
+ _ => value.ToString(),
+ };
+
+ ///
+ /// Determines whether one or more bit fields are set in the current instance.
+ /// Equivalent to calling on .
+ ///
+ /// The value of the instance to investiage
+ /// The flag to check for
+ /// true if the fields set in the flag are also set in the current instance; otherwise false .
+ /// If the underlying value of is zero, the method returns true.
+ /// This is consistent with the behaviour of
+ public static bool HasFlagFast(this MyTestNameSpace.MyEnum value, MyTestNameSpace.MyEnum flag)
+ => flag == 0 ? true : (value & flag) == flag;
+
+ ///
+ /// Returns a boolean telling whether the given enum value exists in the enumeration.
+ ///
+ /// The value to check if it's defined
+ /// true if the value exists in the enumeration, false otherwise
+ public static bool IsDefined(MyTestNameSpace.MyEnum value)
+ => value switch
+ {
+ MyTestNameSpace.MyEnum.First => true,
+ MyTestNameSpace.MyEnum.Second => true,
+ MyTestNameSpace.MyEnum.Third => 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
+ /// true if a member with the name exists in the enumeration, false otherwise
+ public static bool IsDefined(string name) => IsDefined(name, allowMatchingMetadataAttribute: false);
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or if a member decorated with a
+ /// with the required name exists.
+ ///
+ /// The name to check if it's defined
+ /// If true , considers the value of metadata attributes,otherwise ignores them
+ /// true if a member with the name exists in the enumeration, or a member is decorated
+ /// with a with the name, false otherwise
+ public static bool IsDefined(string name, bool allowMatchingMetadataAttribute)
+ {
+ return name switch
+ {
+ nameof(MyTestNameSpace.MyEnum.First) => true,
+ nameof(MyTestNameSpace.MyEnum.Second) => true,
+ nameof(MyTestNameSpace.MyEnum.Third) => true,
+ _ => false,
+ };
+ }
+
+#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration
+ ///
+ /// The name to check if it's defined
+ /// true if a member with the name exists in the enumeration, false otherwise
+ public static bool IsDefined(in ReadOnlySpan name) => IsDefined(name, allowMatchingMetadataAttribute: false);
+
+ ///
+ /// Returns a boolean telling whether an enum with the given name exists in the enumeration,
+ /// or optionally if a member decorated with a
+ /// with the required name exists.
+ /// Slower then the overload, but doesn't allocate memory./>
+ ///
+ /// The name to check if it's defined
+ /// If true , considers the value of metadata attributes,otherwise ignores them
+ /// true if a member with the name exists in the enumeration, or a member is decorated
+ /// with a with the name, false otherwise
+ public static bool IsDefined(in ReadOnlySpan name, bool allowMatchingMetadataAttribute)
+ {
+ return name switch
+ {
+ ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.First).AsSpan(), System.StringComparison.Ordinal) => true,
+ ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.Second).AsSpan(), System.StringComparison.Ordinal) => true,
+ ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.Third).AsSpan(), System.StringComparison.Ordinal) => true,
+ _ => false,
+ };
+ }
+#endif
+
+ ///
+ /// 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.
+ /// true if the value parameter was converted successfully; otherwise, false .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out MyTestNameSpace.MyEnum value)
+ => TryParse(name, out value, false, false);
+
+ ///
+ /// 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.
+ /// true to read value in case insensitive mode; false to read value in case sensitive mode.
+ /// true if the value parameter was converted successfully; otherwise, false .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out MyTestNameSpace.MyEnum value,
+ bool ignoreCase)
+ => TryParse(name, out value, ignoreCase, false);
+
+ ///
+ /// 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.
+ /// true to read value in case insensitive mode; false to read value in case sensitive mode.
+ /// If true , considers the value included in metadata attributes such as
+ /// when parsing, otherwise only considers the member names.
+ /// true if the value parameter was converted successfully; otherwise, false .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ string? name,
+ out MyTestNameSpace.MyEnum value,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ {
+ if (ignoreCase)
+ {
+ switch (name)
+ {
+ case string s when s.Equals(nameof(MyTestNameSpace.MyEnum.First), System.StringComparison.OrdinalIgnoreCase):
+ value = MyTestNameSpace.MyEnum.First;
+ return true;
+ case string s when s.Equals(nameof(MyTestNameSpace.MyEnum.Second), System.StringComparison.OrdinalIgnoreCase):
+ value = MyTestNameSpace.MyEnum.Second;
+ return true;
+ case string s when s.Equals(nameof(MyTestNameSpace.MyEnum.Third), System.StringComparison.OrdinalIgnoreCase):
+ value = MyTestNameSpace.MyEnum.Third;
+ return true;
+ case string s when int.TryParse(name, out var val):
+ value = (MyTestNameSpace.MyEnum)val;
+ return true;
+ default:
+ value = default;
+ return false;
+ }
+ }
+ else
+ {
+ switch (name)
+ {
+ case nameof(MyTestNameSpace.MyEnum.First):
+ value = MyTestNameSpace.MyEnum.First;
+ return true;
+ case nameof(MyTestNameSpace.MyEnum.Second):
+ value = MyTestNameSpace.MyEnum.Second;
+ return true;
+ case nameof(MyTestNameSpace.MyEnum.Third):
+ value = MyTestNameSpace.MyEnum.Third;
+ return true;
+ case string s when int.TryParse(name, out var val):
+ value = (MyTestNameSpace.MyEnum)val;
+ return true;
+ default:
+ value = default;
+ return false;
+ }
+ }
+ }
+
+#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0
+ ///
+ /// 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.
+ /// true if the value parameter was converted successfully; otherwise, false .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in ReadOnlySpan name,
+ out MyTestNameSpace.MyEnum value)
+ => TryParse(name, out value, false, false);
+
+ ///
+ /// 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.
+ /// true to read value in case insensitive mode; false to read value in case sensitive mode.
+ /// true if the value parameter was converted successfully; otherwise, false .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in ReadOnlySpan name,
+ out MyTestNameSpace.MyEnum value,
+ bool ignoreCase)
+ => TryParse(name, out value, ignoreCase, false);
+
+ ///
+ /// 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.
+ /// true to read value in case insensitive mode; false to read value in case sensitive mode.
+ /// If true , considers the value included in metadata attributes such as
+ /// when parsing, otherwise only considers the member names.
+ /// true if the value parameter was converted successfully; otherwise, false .
+ public static bool TryParse(
+#if NETCOREAPP3_0_OR_GREATER
+ [System.Diagnostics.CodeAnalysis.NotNullWhen(true)]
+#endif
+ in ReadOnlySpan name,
+ out MyTestNameSpace.MyEnum result,
+ bool ignoreCase,
+ bool allowMatchingMetadataAttribute)
+ {
+ if (ignoreCase)
+ {
+ switch (name)
+ {
+ case ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.First).AsSpan(), System.StringComparison.OrdinalIgnoreCase):
+ result = MyTestNameSpace.MyEnum.First;
+ return true;
+ case ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.Second).AsSpan(), System.StringComparison.OrdinalIgnoreCase):
+ result = MyTestNameSpace.MyEnum.Second;
+ return true;
+ case ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.Third).AsSpan(), System.StringComparison.OrdinalIgnoreCase):
+ result = MyTestNameSpace.MyEnum.Third;
+ return true;
+ case ReadOnlySpan current when int.TryParse(name, out var numericResult):
+ result = (MyTestNameSpace.MyEnum)numericResult;
+ return true;
+ default:
+ result = default;
+ return false;
+ }
+ }
+ else
+ {
+ switch (name)
+ {
+ case ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.First).AsSpan(), System.StringComparison.Ordinal):
+ result = MyTestNameSpace.MyEnum.First;
+ return true;
+ case ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.Second).AsSpan(), System.StringComparison.Ordinal):
+ result = MyTestNameSpace.MyEnum.Second;
+ return true;
+ case ReadOnlySpan current when current.Equals(nameof(MyTestNameSpace.MyEnum.Third).AsSpan(), System.StringComparison.Ordinal):
+ result = MyTestNameSpace.MyEnum.Third;
+ return true;
+ case ReadOnlySpan current when int.TryParse(name, out var numericResult):
+ result = (MyTestNameSpace.MyEnum)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 MyTestNameSpace.MyEnum[] GetValues()
+ {
+ return new[]
+ {
+ MyTestNameSpace.MyEnum.First,
+ MyTestNameSpace.MyEnum.Second,
+ MyTestNameSpace.MyEnum.Third,
+ };
+ }
+
+ ///
+ /// 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()
+ {
+ return new[]
+ {
+ nameof(MyTestNameSpace.MyEnum.First),
+ nameof(MyTestNameSpace.MyEnum.Second),
+ nameof(MyTestNameSpace.MyEnum.Third),
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly.verified.txt
index a2111aa..5975495 100644
--- a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly.verified.txt
+++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/SourceGenerationHelperSnapshotTests.GeneratesFlagsEnumCorrectly.verified.txt
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// This code was generated by the NetEscapades.EnumGenerators source generator
//
@@ -43,17 +43,15 @@ namespace Something.Blah
///
/// Determines whether one or more bit fields are set in the current instance.
- /// Equivalent to calling value.HasFlag(flag)
+ /// Equivalent to calling on .
///
/// The value of the instance to investiage
/// The flag to check for
/// true if the fields set in the flag are also set in the current instance; otherwise false .
- public static bool HasFlag(this Something.Blah.ShortName value, Something.Blah.ShortName flag)
- => value switch
- {
- 0 => flag.Equals(0),
- _ => (value & flag) != 0,
- };
+ /// If the underlying value of is zero, the method returns true.
+ /// This is consistent with the behaviour of
+ public static bool HasFlagFast(this Something.Blah.ShortName value, Something.Blah.ShortName flag)
+ => flag == 0 ? true : (value & flag) == flag;
///
/// Returns a boolean telling whether the given enum value exists in the enumeration.