Search code examples
c#compiler-constructionenumsvisual-studio-2013enum-flags

Unexpected behavior between [Flags] enum : long vs [Flags] enum : ulong


Compiles but shouldn't

[Flags]
enum TransactionData : long  // 64 bits.  Last bit is sign bit, but I'm putting data there
{
    None = 0,
    Color1 = 1 << 63,
}

Errors but shouldn't

[Flags]
enum TransactionData : ulong  // 64 bits. No sign bit.  Not allowed to put data there
{
    None = 0,
    Color1 = 1 << 63,
}

Compiler Error Text:

-2147483648 cannot be converted to a ulong

Question:

I would expect the opposite to occur. Can anyone explain why this is?

Also how I can print this flags attribute to a byte[] for inspection?

 var eee  = TransactionData.None | TransactionData.Color1
 // How do I convert eee to byte[]?

Solution

  • Note that 1 << 63 isn't a ulong or even a long. The compiler interprets it as an int. Observe the following example:

    enum TransactionData : long
    {
        None = 0,
        Color1 = 1 << 31,
        Color2 = 1 << 63,
    }
    
    Console.WriteLine(TransactionData.Color1 == TransactionData.Color2); // True
    

    However, you can coerce the compiler into interpreting it as a ulong by adding ul to the end:

    enum TransactionData : ulong
    {
        None = 0,
        Color1 = 1ul << 63,
    }
    

    Although many people prefer using an upper case L because the lowercase l looks a lot like a number 1. A full list of what suffixes are supported by the compiler can be found here.

    Also, I should point out that 1ul << 63 is actually 64 bits wide (it's one bit, shifted by 63 bits).