0

假设我有以下代码:

[Flags]
enum MyFlags
{
    None = 0,
    A = 1,
    B = 2,
    C = 4,
    D = 8,
    E = 16,
    // ...
}

当标志的数量变得非常大时,这显然不是最佳的。通过优化,意味着可读,而不是快速或节省内存。

对于组合标志,例如

AB = 3

我们可以很容易地使用

AB = A | B

相反,它更具可读性。
并用于组合所有标志

All = A | B | C | ...

使用会更有利

All = ~None

相反,即使我们没有充分利用所有可用的 32/64 位。

但是常规值呢?

之间

E = 16
E = 0b10000
E = 0x10
E = 1 << 4

或者我没有想到的其他方式,哪种方式最适合大量标志?

或者换句话说,在 C# 中设置标志值的(商定)约定是什么?

让我们假设为了论证,值不会对齐,所以代码可能看起来像这样

None = 0,
Apple = 1,
Banana = 2,
StrangeFruit = Apple | Banana,
Cherry = 4,
Date = 8,
Elderberry = 16,
// ...
4

2 回答 2

7

对于常规值,我喜欢1 << n:在您花了(短)时间理解它之后,很容易看到发生了什么,很难搞砸,并且不需要十六进制/二进制转换/思考。

[Flags]
enum MyFlags
{
    None = 0,
    A = 1 << 0,
    B = 1 << 1,
    C = 1 << 2,
    D = 1 << 3,
    E = 1 << 4,
    // ...
    Lastly = 1 << 31,
}

至于实际定义的约定,我认为不存在。MS 的枚举设计指南说

√ DO对标志枚举值使用 2 的幂,以便它们可以使用按位或运算自由组合。

但没有指定如何在您的源代码中编写它(这些是与语言无关的指南;在 C# 中可能好的东西甚至可能在另一种 .Net 语言中不起作用)。

于 2014-05-16T16:12:47.840 回答
1

我不认为有任何既定的惯例。您可以参考Cwalina, Abrahms 的框架设计指南以获得指导。

我更喜欢使用十六进制方法0x00, 0x01。您使用 1、2、4、8,然后向左移动到下一个位置。对于通常组合的值,我更喜欢您描述的 OR'ing 方法。

例子:

[Flags]
public enum Directions
{
    None = 0x00,
    Left = 0x01,
    Right = 0x02,
    Top = 0x04,
    Bottom = 0x08,
    Forward = 0x10,
    Backward = 0x20,
    TopLeft = Top | Left,
    TopRight = Top | Right,
    BottomLeft = Bottom | Left,
    BottomRight = Bottom | Right
}
于 2014-05-16T15:58:00.500 回答