In order for flag enums to work as expected, the enum constants need to be powers of 2.
In your example the binary values look like this (I show 4 bits only for sake of simplicity)
Left = 0 0000
Right = 1 0001
Top = 2 0010
Bottom = 3 0011
Left | Right | Top | Bottom = 0011 which is 3 or Bottom again
If you choose powers of 2, exactly one bit is set and you get
Left = 1 = 2^0 0001
Right = 2 = 2^1 0010
Top = 4 = 2^2 0100
Bottom = 8 = 2^3 1000
Left | Right | Top | Bottom = 1111
I.e., with powers of 2, different bits are set and therefore they combine neatly with the bitwise OR operator (|).
Since C# 7.0 you can use binary literals
[Flags]
public enum Orientations {
Left = 0b0001,
Right = 0b0010,
Top = 0b0100,
Bottom = 0b1000
};
In previous versions of C# you can also use the left shift operator to get powers of 2
[Flags]
public enum Orientations {
Left = 1 << 0,
Right = 1 << 1,
Top = 1 << 2,
Bottom = 1 << 3
};
It is a good practice to also include the enum constant None = 0
because enum fields are initialized to default(MyEnum) == 0
, otherwise resulting in a value having no corresponding enum constant.
You can also create new combined enum values like this
[Flags]
public enum Orientations {
None = 0,
Left = 1 << 0,
Right = 1 << 1,
Top = 1 << 2,
Bottom = 1 << 3,
Horizontal = Left | Right,
Vertical = Top | Bottom,
All = Horizontal | Vertical
};
Note that every enum has an implicit conversion from 0. Therefore you could do this test
if((myOrientations & Orientations.Vertical) != 0) {
// We have at least a Top or Bottom orientation or both
}