Check if an enum contains more than one flag [duplicate]

此生再无相见时 提交于 2021-01-03 22:12:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!