为什么标志枚举通常用hex数值定义
很多时候,我看到使用hex值的标志枚举声明。 例如:
[Flags] public enum MyEnum { None = 0x0, Flag1 = 0x1, Flag2 = 0x2, Flag3 = 0x4, Flag4 = 0x8, Flag5 = 0x10 }
当我声明一个枚举时,我通常会这样声明:
[Flags] public enum MyEnum { None = 0, Flag1 = 1, Flag2 = 2, Flag3 = 4, Flag4 = 8, Flag5 = 16 }
为什么有些人select用hex而不是十进制来编写数值,是否有理由或理由? 我看到它的方式,使用hex值时会更容易混淆,并且不小心写入Flag5 = 0x16
而不是Flag5 = 0x10
。
理由可能有所不同,但是我看到的一个好处是,hex提醒你:“好的,我们不是在处理任意人类发明的基数为10的世界的数字,而是处理位数 – 机器的世界 – 要按照规定发挥作用。“ hex很less被使用,除非你正在处理数据的内存布局相对较低的主题。 使用它暗示事实,那就是我们现在所处的状况。
另外,我不确定C#,但我知道在C x << y
是一个有效的编译时常量。 使用位移似乎是最清楚的:
[Flags] public enum MyEnum { None = 0, Flag1 = 1 << 0, Flag2 = 1 << 1, Flag3 = 1 << 2, Flag4 = 1 << 3, Flag5 = 1 << 4 }
这很容易看出这些是二进制标志。
None = 0x0, // == 00000 Flag1 = 0x1, // == 00001 Flag2 = 0x2, // == 00010 Flag3 = 0x4, // == 00100 Flag4 = 0x8, // == 01000 Flag5 = 0x10 // == 10000
虽然进展使得它更清晰:
Flag6 = 0x20 // == 00100000 Flag7 = 0x40 // == 01000000 Flag8 = 0x80 // == 10000000
我认为这只是因为序列总是1,2,4,8,然后加上0。
如你看到的:
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的顺序,你就可以build立所有后面的标志,而不必记住2的权力
因为[Flags]
意味着枚举实际上是一个位域 。 使用[Flags]
,可以使用按位AND( &
)和OR( |
)运算符来组合标志。 当处理这样的二进制值时,使用hex值几乎总是更清楚。 这就是我们首先使用hex的原因。 每个hex字符恰好对应一个半字节(四位)。 使用十进制,这个1对4映射不适用。
因为有一个机械的,简单的方法来加倍hex的幂。 十进制,这是很难的。 它需要在你的头上长时间的乘法。 hex是一个简单的改变。 你可以一直执行到1UL << 63
,你不能用小数来做。
因为比特位于旗子的人类更容易遵守。 每个hex数字可以适合4位二进制。
0x0 = 0000 0x1 = 0001 0x2 = 0010 0x3 = 0011 ... and so on 0xF = 1111
通常,您希望标志不重叠位,最简单的方法是使用hex值来声明标志。
所以,如果你需要16位的标志,你将使用4位hex值,这样你可以避免错误的值:
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