问题
I am trying to check if an "enum instance" contains more than one flag.
[Flags]
public enum Foo
{
Bar = 1,
Far = 2
}
var multiState = Foo.Bar | Foo.Far;
MoreThanOneFlag(multiState); // True
var singleState = Foo.Bar;
MoreThanOneFlag(singleState); // False
Additionally I really don't wanna use something like the following:
var state = Foo.Bar | Foo.Far;
Console.WriteLine(state.ToString().Count(x => x == ',') > 0); // True
Note, I do not care which Flags the "instance" contains, I just want to know if there are more than one.
回答1:
I am trying to check if an "enum instance" contains more than one flag. I do not care which Flags the "instance" contains, I just want to know if there are more than one
Additionally I really don't wanna use something like the following:
var state = Foo.Bar | Foo.Far;
Console.WriteLine(state.ToString().Count(x => x == ',') > 0); // True
There are more than a few different ways to accomplish what you want, I propose to do a bit (bitwise) check:
public static bool MoreThanOneFlag<TValue>(TValue flag) where TValue : Enum => (Convert.ToInt32(flag) & (Convert.ToInt32(flag) - 1)) != 0;
In the above code block, we check if flag
is not a power of two by checking using flag & (flag-1)) != 0
(the & operator) which computes the bitwise logical AND of its operands. If there's only one flag set, we assume then that the value would be a power of two, otherwise it's a non power of two.
Or, if you don't want a helper function just perform that check anywhere:
bool value = (multiState & (multiState -1)) != 0;
For more information about bitwise, please check out more here.
References :
Bitwise and shift operators (C# reference)
回答2:
You can use the binary logarithm function on the enum
value and then check if the result is an integer.
The following example defines am Extension Method helper, which returns true
when multiple flags are set:
HelperExtenxsions.cs
public static class HelperExtenxsions
{
public static bool HasMultipleFlags(this IConvertible enumValue)
{
return Math.Log(enumValue.ToInt32(CultureInfo.InvariantCulture.NumberFormat), 2) % 1 != 0;
}
}
Foo.cs
[Flags]
public enum Foo
{
Bar = 1,
Far = 2
}
Program.cs
public static void Main()
{
var enumValue = Foo.Bar | Foo.Far;
Console.WriteLine(enumValue.HasMultipleFlags()); // Prints 'True'
enumValue = Foo.Bar;
Console.WriteLine(enumValue.HasMultipleFlags()); // Prints 'False'
}
回答3:
You can use Enum.GetValues
in conjunction with Enum.HasFlag(Enum)
to iterate over each constant & determine if the bit field(s) are set in the current Instance and return its count.
[Flags]
public enum Foo
{
One = 1,
Two = 2,
Four = 4,
Eight = 8
}
var state1 = Foo.One;
var state2 = Foo.Two;//
var state3 = Foo.One | Foo.Two;
var state4 = Foo.Two | Foo.Four;
Console.WriteLine(MoreThanOneFlag(state1));//false
Console.WriteLine(MoreThanOneFlag(state2));//false
Console.WriteLine(MoreThanOneFlag(state3));//true
Console.WriteLine(MoreThanOneFlag(state4));// true
private static bool MoreThanOneFlag<TEnum>(TEnum state) where TEnum : Enum
{
var names = Enum.GetValues(typeof(TEnum));
var Flagcounter = names.OfType<TEnum>().Where(x=>state.HasFlag((TEnum)x)).Count();
return Flagcounter > 1 ? true : false;
}
Note: While Enum.HasFlags
may not the apt solution if you're app demands performance but it is much reliable, clean, and makes the code very obvious and expressive
Reference:
C# Enum.HasFlag vs. Bitwise AND Operator Check
来源:https://stackoverflow.com/questions/60466268/check-if-an-enum-contains-more-than-one-flag