# Get elementary values from a flagged enum

I created a little function that returns the elementary values from a flagged enum. By "elementary" I mean the values that are powers of 2, excluding any combined enum values. I was a bit surprised I couldn't find a buit-in method for this in .Net (or I missed it).

Let's take this flagged enum:

[Flags]
public enum WeekDay
{
Monday = 1 << 0,
Tuesday = 1 << 1,
Wednesday = 1 << 2,
Thursday = 1 << 3,
Friday = 1 << 4,
Saturday = 1 << 5,
Sunday = 1 << 6,

WeekendDay = Saturday | Sunday,
BusinessDay = Monday | Tuesday | Wednesday | Thursday | Friday
}


Since the binary representation of its values looks as follows...

1
10
100
1000
10000
100000
1000000

1100000
11111


...I came up with this function to extract the elementary values:

public IEnumerable<TEnum> GetElementaryValues<TEnum>()
where TEnum: Enum
{
return Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Where(v =>
{
var intValue = Convert.ToInt64(v);
var binary = Convert.ToString(intValue, 2);
return !binary.Skip(1).Any(c => c == '1');
});
}


Which basically says: return each value that hasn't got a 1 beyond its first character.

Doest this look OK? Can it be improved? My feeling is that it's a lot of expensive code for such a simple task.

## 1 Answer

The way to test for a power of two, where x is an unsigned integer type is

( x != 0 ) && ( ( x & ( x - 1 ) ) == 0 )


To understand why this works, it's fairly easy to see that if x is a power of two, then x & (x -1 ) is zero.

If x is not a power of two, then only the bits up to the first non-zero bit are changed when you subtract one, and that is not the most significant bit, so the most significant bit is not cleared, and so x & (x - 1 ) is non-zero, as required.

Zero is a special case - it's not a power of two, so an extra test is needed, also ( x - 1 ) overflows if x is zero.

• I knew "something" with bits should be possible, but didn't figure out this one. Perfect, thanks! Excluding 0 is in line with flagged enum best practices, so that's OK. – Gert Arnold Mar 13 '19 at 13:17