Enum flags over 2^32
Asked Answered
C

3

67

I am using Enum flags in my application. The Enum can have around 50+ values, so values go up to 2^50. I was just wondering, can I use Math.Pow(2, variable) to calculate these?

When I try to do that I get a constant value compile-time error. Is there another way, other than calculating these powers of 2 manually and putting it in?

Here's what I am doing:

[Flags]
internal enum RiskStates : long
    {
        None = 0,
        AL = Convert.ToInt64(Math.Pow(2,0)),
        AK = 2,
        AZ = 4,
        AR = 8,
        CA = 16,
        CO = 32,
        CT = 64,
        DC = 128,
        DE = 256,
        FL = 512,
        GA = 1024,
        HI = 2048,
        ID = 4096,
        IL = 8192,
        IN = 16384,
        IA = 32768,
        KS = 65536,
        KY = 131072,
        LA = 262144,
        ME = 524288,
        MD = 1048576,
        MA = 2097152,
        MI = 4194304
}
Choreography answered 26/9, 2013 at 7:20 Comment(11)
I would use a regular enum with a HashSet.Kaph
Out of curiosity, why do the values need to go up in powers of 2?Tallinn
@deed02392: because of the flag nature of this enum. You can combine multiple values. Each values "own" one bit in the value. AZ + AK will be 6. Using powers of 2 avoid unwanted collision of combinationsCoachwhip
Ahh, like a state machine's flags - so you can always determine how many and which enum flags are set. Very nice.Tallinn
Like everyone else I hate answers that tell you not to do something rather than how to do it, but it seems completely incredible that a Flags enum with 50 different values is the right solution for whatever your problem is. Either not every combination of all the 50 flags is really possible, in which case you should use one or more simpler enums, or they are, and you could be using a more intelligent data structure??Elmiraelmo
@Elmiraelmo the individual flags appear to be the 50 states of the US. It would be an amusing party game to pick at random a subset of n the 50 and try and find some unique property such that all n have that property and the other 50-n all don't. Well, amusing or not, depending on the party guests...Psychometry
I kind of assumed that this is an artificial example since he said 'around 50+' and not exactly 50. If the values are the US states then what I said applies even more so.Elmiraelmo
@jwg: Hypothetical scenario: "in which of the following 50 states have you lived in the past 3 years?" You're limited in scope to a binary decision about a strongly-typed set.Cholera
The inventor of 64-bit CPUs is turning in his grave somewhere.Elmiraelmo
@Psychometry I think that your parties are a little too wild for me.Farouche
@AndrewCoonce, that would be a great example of where to use a List<State> instead of a flags enum. The key observation is that very few people are likely to have lived in ten or more states. The List handles the small sets and singletons well, whereas the enum handles the huge number of extremely unlikely larger sets equally well, at the expense of, for example, not finding the count of states very easily.Elmiraelmo
C
129

When I try to do that I get a constant value compile-time error.

You'd actually be okay if you used the L suffix to force it to be a long literal - but it's still not ideal to have to specify them all manually. (It's not "obviously correct" when reading the code.)

You can't use Math.Pow as the expression has to be a compile-time constant - but you can use bit-shifting:

None = 0,
AL = 1L << 0,
AK = 1L << 1,
AZ = 1L << 2

etc. I'd argue that's more readable anyway :)

Chapel answered 26/9, 2013 at 7:21 Comment(5)
Are you saying you don't know all digits of each power of two at least up to 2^64 by heart? You burst my bubble!Sami
@MichaelKjörling: Well of course I do, but I have to consider mere mortals too...Chapel
I have to imagine bit shifting is also a wee bit faster to type... Unless you can type infinity words per minute.Omnibus
@JonSkeet I want to upvote that comment but it's at 42 and I just can't bring myself to change that!Infusorian
@RobH I took the bullet. Knock yourself out!Tie
L
9

If you change to using non-decimal notations where the powers of 2 are more regular then you will no longer need to generate them automatically, e.g.:

// octal
AL = 0001L,
AK = 0002L,
AZ = 0004L,
AR = 0010L,
CA = 0020L,
CO = 0040L,
CT = 0100L,
...

// hexadecimal
AL = 0x001L,
AK = 0x002L,
AZ = 0x004L,
AR = 0x008L,
CA = 0x010L,
CO = 0x020L,
CT = 0x040L,
...
Lina answered 30/9, 2013 at 23:18 Comment(2)
Doesn't answer the question.Zola
But it does address the problem which is that there is difficulty in entering, verifying and understanding the enum constants when specified in base 10. One solution is to auto generate, as requested by the OP, the other is to switch to a clearer base. Updated answer to reflect this better I hope.Lina
O
1

I'd be tempted to consider using BitArray as the underlying structure.

Ought answered 1/10, 2013 at 23:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.