为什么我永远不会在标志枚举中使用0

时间:2012-03-21 18:56:53

标签: c# enums flags

  

可能重复:
  Should an Enum start with a 0 or a 1?

为什么我永远不会在标志枚举中使用0?我现在已多次阅读此内容并希望如此 知道原因:)

7 个答案:

答案 0 :(得分:21)

因为Flag枚举是位集合或选项集。

0值将是所有集合的一部分,或者不是。它只是行不通。

答案 1 :(得分:18)

  

为什么我永远不会在标志枚举中使用0?

这个问题是基于一个不正确的假设。您应该始终在标志枚举中使用零。它应始终设置为“无”。

除了表示“没有设置任何标志”之外,你不应该使用它。

  

为什么不呢?

因为如果零具有除“无”之外的含义,则会变得非常混乱。人们有理由期望((e & E.X) == E.X)的意思是“X标志是否已设定?”但如果X为零,则此表达式将始终为真,即使逻辑该标志未“设置”。

答案 2 :(得分:3)

虽然零表示没有设置任何位,但将命名常量设为0通常非常有用。

当我设置标志字时,我定义了位的名称,以便它们都代表非默认值。也就是说,枚举值始终初始化为零,将“位”表示的所有选项“关闭”。

这为你的枚举提供了向前兼容性,这样任何创建新值的人都知道如果稍后在你的位域中添加更多标志,任何零位都将是“安全的”。

类似地,组合几个标志来创建一个新的常量名称非常有用,这使得代码更具可读性。

这种危险(以及引用规则的原因)只是你必须意识到单个位值(标志)和表示组或位组合的值之间的区别。

答案 3 :(得分:2)

标记枚举的用法如下:

Flag flags = Flag.First | Flag.Next | Flag.Last;

然后你应该像这样定义你的旗帜:

enum Flag {First = 1, Next = 2, Last = 4};

通过这种方式,您可以查看是否已使用过Flag,例如:

if (flags & Flag.First <> 0) Console.WriteLine("First is set");
if (flags & Flag.Next <> 0) Console.WriteLine("Next is set");
if (flags & Flag.Last <> 0) Console.WriteLine("Last is set");

这就是为什么你只能使用2的幂的值,例如1,2,4,8,16,32,64,128,...

如果flags为0,则认为它为空白。

我希望这会增加你对旗帜枚举的理解。

答案 4 :(得分:1)

因为通常使用标志如下:

var myFlagEnum = MyEnum.Foo | MyEnum.Bar | MyEnum.Bat;

// ...  snip ...

if (myFlagEnum & MyEnum.Foo == MyEnum.Foo) { ...  do something ... };

如果MyEnum.Foo为零,则上述操作无效(对于所有情况,它将返回true)。如果它是1,那么它会起作用。

答案 5 :(得分:1)

一个标志枚举假定它的每个值代表一个选项的存在,并且它在一个枚举位中编码。因此,如果存在特定选项(或为真),则枚举值中的equiveland位设置为(1),否则不设置(0)

因此每个枚举字段都是一个只设置了一个位的值。如果没有选项存在或为真,则组合的枚举值为零,这意味着没有设置任何位。因此,标志枚举中唯一的零字段是一个意味着没有设置,选择或选择任何选项的字段。

例如,假设我们有一个标记枚举,用于编码表格单元格中边框的存在

public enum BorderType
{
    None   = 0x00, // 00000000 in binary
    Top    = 0x01, // 00000001 in binary
    Left   = 0x02, // 00000010 in binary
    Right  = 0x04, // 00000100 in binary
    Bottom = 0x08  // 00001000 in binary
}

如果要显示单元格中存在顶部和底部边框,则应使用值

 Cell.Border = BorderType.Top | BorderType.Bottom; // 0x01 | 0x08 = 0x09 = 00001001 in binary

如果要显示单元格没有边框,则应使用值

 Cell.Border = BorderType.None; // 0x00 = 00000000 in binary

所以你不应该在标志枚举中使用零作为选项的值,但是你应该总是使用零作为值,这意味着没有设置任何标志。

答案 6 :(得分:0)

我真的没有看到问题。

enum Where {Nowhere=0x00, Left=0x01, Right=0x02, Both=Left|Right};
Where thevalue = Where.Both;
bool result = (thevalue&Where.Nowhere)==Where.Nowhere;

当然结果是真的!你有什么期望?在这里,想一想。

bool result1 = (thevalue&Where.Left)==Where.Left;
bool result2 = (thevalue&Where.Right)==Where.Right;
bool result3 = (thevalue&Where.Both)==Where.Both;

这些全部是真的!为什么Nowhere应该特别?关于0没什么特别的!