0

Let's say I have following code:

[Flags]
enum MyFlags
{
    None = 0,
    A = 1,
    B = 2,
    C = 4,
    D = 8,
    E = 16,
    // ...
}

This is obviously not going to be optimal when the amount of flags grow very large. And by optimal, mean readable, not fast or memory saving.

For combined flags, such as

AB = 3

we can easily use

AB = A | B

instead, which is more readable.
And for combining all flags

All = A | B | C | ...

it would be more favorable to use

All = ~None

instead, even if we don't make full use of all 32/64 bits available.

But what about regular values?

Between

E = 16
E = 0b10000
E = 0x10
E = 1 << 4

or other ways I haven't thought of, which would be best suited for a large amount of flags?

Or in other words, what is the (agreed upon) convention for setting values for flags in C#?

Let us assume for the sake of argument, that the values will not be aligned, so the code might very well look like this

None = 0,
Apple = 1,
Banana = 2,
StrangeFruit = Apple | Banana,
Cherry = 4,
Date = 8,
Elderberry = 16,
// ...
Nolonar
  • 5,962
  • 3
  • 36
  • 55
  • Why do you feel the initial example isn't readable? How many members of flags enum do you plan to actually have when you say "very large"? – Preston Guillot May 16 '14 at 15:54
  • 1
    @PrestonGuillot I have a project, in which I already have to manage 15 distinct flags (without flag None), and there might be more in the future. Maybe 32768 isn't exactly unreadable, but it is easy to make a mistake and completely break all flags. – Nolonar May 16 '14 at 15:56
  • But if you really need 32768 flags I'd bet it's more likely that the design isn't really that well thought... I have never seen an enum that *needs* to be that huge. –  May 16 '14 at 16:10
  • @Areks Distinct members of a `Flags` enum are valued with powers of 2 so they can be combined with bitwise operations - the 15th distinct member of the enum is valued at 32768, not the 2^15th. – Preston Guillot May 16 '14 at 17:44
  • @PrestonGuillot My bad, I totally misundertood what I read. I don't know why I understood that there could be 32768 members in the enum. –  May 16 '14 at 21:14

2 Answers2

7

For regular values, I like 1 << n: after you've taken the (short) time to understand it, it's very easy to see what's going on, hard to mess up, and requires no hex/binary conversion/thinking.

[Flags]
enum MyFlags
{
    None = 0,
    A = 1 << 0,
    B = 1 << 1,
    C = 1 << 2,
    D = 1 << 3,
    E = 1 << 4,
    // ...
    Lastly = 1 << 31,
}

As far as an actual defined convention, I don't think one exists. MS's Enum Design guidelines says

√ DO use powers of two for the flag enum values so they can be freely combined using the bitwise OR operation.

but does not specify how to write this in your source (those are language-agnostic guidelines; what might be good in C# might not even work in another .Net language).

Tim S.
  • 55,448
  • 7
  • 96
  • 122
1

I don't think there's any established convention. You might consult Framework Design Guidelines by Cwalina, Abrahms for guidance.

I prefer to use the hex method 0x00, 0x01. You use 1, 2, 4, 8, and then move left to the next position. For values that are commonly combined, I prefer the OR'ing method you describe.

Example:

[Flags]
public enum Directions
{
    None = 0x00,
    Left = 0x01,
    Right = 0x02,
    Top = 0x04,
    Bottom = 0x08,
    Forward = 0x10,
    Backward = 0x20,
    TopLeft = Top | Left,
    TopRight = Top | Right,
    BottomLeft = Bottom | Left,
    BottomRight = Bottom | Right
}
walkingTarget
  • 408
  • 5
  • 17