4

If I have an enum with multiple values which can be present at the same time, I create a Flags enum:

[Flags]
public enum Foo
{
    None = 0,
    A = 1,
    B = 2,
    C = 4,
    D = 8
}

If I now want to pass the fact that every value is set I would have to do something like this:

Bar bar = new Bar(Foo.A | Foo.B | Foo.C | Foo.D);

Would it be considered bad practice/harmful/blasphemy to add an additional element All?

    All = 15

This would save some space and time when there are a lot of values and passing them all is a common scenario.

As far as I understand the mechanics of flags enums (=bitfields), this should work. Are there any side effects I am missing or other reasons why you should not do that?

magnattic
  • 12,638
  • 13
  • 62
  • 115

4 Answers4

8

You can do that. But maybe you shoudn't use the value 15, but

All = A | B | C | D
Carsten Schütte
  • 4,408
  • 1
  • 20
  • 24
2

There is a dangerous gotcha here where if you change All but the calling components are not recompiled, they will send the old All. If this is fine with you than so be it.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • 4
    Wouldn't that be a general problem with changing enums then? – magnattic May 29 '12 at 21:33
  • The general problem is changing existing defined values in enums. Adding new items to enums doesn't cause anywhere near so many problems. – Joshua May 30 '12 at 03:15
1

Using bitwise operations is much easier to read

[Flags]
public enum MyEnum
{
    None   = 0,
    First  = 1 << 0,
    Second = 1 << 1,
    Third  = 1 << 2,
    Fourth = 1 << 3,
    All = ~(-1 << 4)
}
realstrategos
  • 783
  • 8
  • 7
0

The most likely place this will go wrong is

[Flags]
public enum Foo
{
    None = 0,
    A = 1,
    B = 2,
    C = 4,
    D = 8
    E = 16
    All = 15
}

Us propeller heads tend to be microfocused, added E job done. oops, oh dear, damn....

And then you take the All idea one step further and feel a need for AllbutC.

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39
  • Well, on the other hand the "All" element would have the benefit that you only have to add the new value E at one central point, and not everywhere where you wanted to actually pass "All". In the above example, you would not have to adjust the line `Bar bar = new Bar(Foo.All)` after you updated the enum. – magnattic May 29 '12 at 21:53
  • And if you really wanted to pass All but C, it would still be quicker for an enum with 20 values to use `Bar bar = new Bar(Foo.All ^ Foo.C)` than to write the other 19 out in full. – magnattic May 29 '12 at 21:59
  • Agreed, but there's an assumption in there, that All when it meant 15 now means All as 31. Another option would be to cheat and make All 255 depending on how many flags, still that assumption though. – Tony Hopkinson May 29 '12 at 22:03
  • @atticae , agreed, but some are bit weak on the boolean algebra front and ALlbutC is more readable. The fact that it now isn't AllbutC because it doesn't include F, is in my opinion something of a pitfall, but I don't have a problem with boolean algebra and I do have one with implicit assumptions like All is All. – Tony Hopkinson May 29 '12 at 22:09
  • You can also use All = 0xffffffff, this will make sure that all bits are set and All is always All. But this is baaaad code. – Carsten Schütte May 30 '12 at 07:34