Why are flag enums usually defined with hexadecimal values
我经常看到使用十六进制值的标志枚举声明。例如:
1 2 3 4 5 6 7 8 9 10 | [Flags] public enum MyEnum { None = 0x0, Flag1 = 0x1, Flag2 = 0x2, Flag3 = 0x4, Flag4 = 0x8, Flag5 = 0x10 } |
当我声明枚举时,我通常这样声明它:
1 2 3 4 5 6 7 8 9 10 | [Flags] public enum MyEnum { None = 0, Flag1 = 1, Flag2 = 2, Flag3 = 4, Flag4 = 8, Flag5 = 16 } |
为什么有些人选择用十六进制而不是十进制来写这个值呢?在我看来,当使用十六进制值并意外地写入
理性可能有所不同,但我看到的一个优点是十六进制提醒你:"好吧,我们不再处理以十为基数的任意人类发明世界中的数字。我们要处理的是位——机器的世界——我们要按照它的规则来处理。"十六进制很少被使用,除非你处理的是相对低级的主题,而数据的内存布局很重要。使用它暗示了这样一个事实,那就是我们现在的处境。
另外,我不确定C,但我知道在C
1 2 3 4 5 6 7 8 9 10 | [Flags] public enum MyEnum { None = 0, Flag1 = 1 << 0, Flag2 = 1 << 1, Flag3 = 1 << 2, Flag4 = 1 << 3, Flag5 = 1 << 4 } |
这使得很容易看到这些是二进制标志。
1 2 3 4 5 6 | None = 0x0, // == 00000 Flag1 = 0x1, // == 00001 Flag2 = 0x2, // == 00010 Flag3 = 0x4, // == 00100 Flag4 = 0x8, // == 01000 Flag5 = 0x10 // == 10000 |
尽管这一进展使情况更加明朗:
1 2 3 | Flag6 = 0x20 // == 00100000 Flag7 = 0x40 // == 01000000 Flag8 = 0x80 // == 10000000 |
我认为这只是因为序列总是1,2,4,8,然后加上0。
如您所见:
1 2 3 4 5 6 7 8 9 10 11 12 | 0x1 = 1 0x2 = 2 0x4 = 4 0x8 = 8 0x10 = 16 0x20 = 32 0x40 = 64 0x80 = 128 0x100 = 256 0x200 = 512 0x400 = 1024 0x800 = 2048 |
等等,只要你记住序列1-2-4-8,你就可以构建所有随后的标记,而不必记住2的幂次
因为
因为有一种机械的,简单的方法可以使两个六角的幂加倍。在十进制中,这很难。这需要你头脑中长时间的乘法运算。十六进制是一个简单的变化。你可以一直执行到
因为在旗子上的位更容易跟随人类。每个十六进制数字可以容纳4位二进制。
1 2 3 4 5 6 7 8 | 0x0 = 0000 0x1 = 0001 0x2 = 0010 0x3 = 0011 ... and so on 0xF = 1111 |
通常,您希望标记不重叠位,最简单的方法是使用十六进制值来声明标记。
因此,如果需要16位的标志,您将使用4位十六进制值,这样可以避免错误的值:
1 2 3 4 5 6 7 8 9 | 0x0001 //= 1 = 000000000000 0001 0x0002 //= 2 = 000000000000 0010 0x0004 //= 4 = 000000000000 0100 0x0008 //= 8 = 000000000000 1000 ... 0x0010 //= 16 = 0000 0000 0001 0000 0x0020 //= 32 = 0000 0000 0010 0000 ... 0x8000 //= 32768 = 1000 0000 0000 0000 |