131

很多时候,我看到使用十六进制值的标志枚举声明。例如:

[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
}

为什么有些人选择用十六进制而不是十进制写值是否有理由或理由?在我看来,使用十六进制值并意外写入Flag5 = 0x16而不是Flag5 = 0x10.

4

6 回答 6

195

基本原理可能有所不同,但我看到的一个优势是十六进制提醒您:“好吧,我们不再处理人类发明的以十为底的任意世界中的数字了。我们正在处理比特 - 机器的世界 - 我们会按照它的规则玩。” 除非您正在处理数据的内存布局很重要的相对较低级别的主题,否则很少使用十六进制。使用它暗示了我们现在所处的情况。

另外,我不确定 C#,但我知道在 Cx << y中是一个有效的编译时常量。使用位移似乎是最清楚的:

[Flags]
public enum MyEnum
{
    None  = 0,
    Flag1 = 1 << 0,  //1
    Flag2 = 1 << 1,  //2
    Flag3 = 1 << 2,  //4
    Flag4 = 1 << 3,  //8
    Flag5 = 1 << 4   //16
}
于 2012-11-04T20:47:40.393 回答
47

很容易看出这些是二进制标志。

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
于 2012-11-04T20:42:03.403 回答
44

我认为这只是因为序列始终是 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,您就可以构建所有后续标志,而无需记住 2 的幂

于 2014-08-05T14:02:47.620 回答
16

因为[Flags]意味着枚举实际上是一个位域。您可以使用[Flags]按位 AND ( &) 和 OR ( |) 运算符来组合标志。在处理这样的二进制值时,使用十六进制值几乎总是更清楚。这就是我们首先使用十六进制的原因。每个十六进制字符恰好对应一个半字节(四位)。对于十进制,这种 1 到 4 映射不成立。

于 2012-11-04T20:42:34.630 回答
5

因为有一种机械的、简单的方法可以将十六进制的二的幂加倍。在十进制中,这很难。它需要在您的脑海中进行长时间的乘法运算。在十六进制中,这是一个简单的更改。您可以一直执行此操作,直到1UL << 63您无法以十进制执行此操作。

于 2012-11-08T21:04:39.373 回答
4

因为位在标志中的人更容易理解。每个十六进制数字可以适合 4 位二进制。

0x0 = 0000
0x1 = 0001
0x2 = 0010
0x3 = 0011

... and so on

0xF = 1111

通常你希望你的标志不重叠位,最简单的实现和可视化它的方法是使用十六进制值来声明你的标志。

因此,如果您需要 16 位标志,您将使用 4 位十六进制值,这样可以避免错误值:

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
于 2013-10-08T19:05:12.110 回答