3

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.

Twenty
  • 3,416
  • 2
  • 17
  • 47
  • 1
    There are so may duplicates, like [this](https://stackoverflow.com/questions/1339976/how-to-check-if-any-flags-of-a-flag-combination-are-set) You can use and `&` operator or `HasFlag` method – Pavel Anikhouski Feb 29 '20 at 14:46
  • @PavelAnikhouski I already looked at those, I just want to know **if**, there is more than one flag set. These answers check if a specific flag is set. – Twenty Feb 29 '20 at 14:47
  • 5
    Perform a bit operation... `bool value = (multiState & (multiState -1)) != 0;` – zaggler Feb 29 '20 at 14:49
  • 1
    @Çöđěxěŕ That was actually exactly what I was searching for. Sadly I just noticed I could have searched for set bits, bummer. – Twenty Feb 29 '20 at 14:52
  • Do you have only two flags? (and therefore only one combination of multiple flags) or are you looking for a general solution to this problem – Steve Feb 29 '20 at 14:53
  • @Steve This is just a simple example, it should work for any amount of flags. – Twenty Feb 29 '20 at 14:54
  • 2
    Does this answer your question? [Counting the number of flags set on an enumeration](https://stackoverflow.com/questions/677204/counting-the-number-of-flags-set-on-an-enumeration) – Pavel Anikhouski Feb 29 '20 at 15:04
  • @PavelAnikhouski I didn't really want to count it, the solutions differ, even when just slightly. – Twenty Feb 29 '20 at 15:06
  • 1
    Why do you want to know if your value is a combination? Usually you just want to get the included bits. – HimBromBeere Feb 29 '20 at 15:21
  • 1
    Maybe they want to check for illegal combinations – Chronicle Feb 29 '20 at 15:22
  • 3
    @Çöđěxěŕ This should be answer rather than a comment. – Alsein Feb 29 '20 at 15:22
  • @Liam yes, but actually no. Under this post there are a lot more answers, which are IMHO better suited, for me at least. Additionally some of them are even more faster. – Twenty Dec 04 '20 at 07:13
  • Well those answers should of been added to the older question(s). This should of been closed as a dupe 9 months ago as the question has already been asked multiple times. In fact this is the obvious dupe target for both, [How do I check if more than one enum flag is set?](https://stackoverflow.com/questions/8949567/how-do-i-check-if-more-than-one-enum-flag-is-set) – Liam Dec 04 '20 at 08:37

3 Answers3

1

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'
}
BionicCode
  • 13,277
  • 2
  • 17
  • 33
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)

zaggler
  • 7,254
  • 6
  • 26
  • 47
0

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

Clint
  • 4,701
  • 1
  • 14
  • 27