为什么[Flag]'枚举从0开始并递增1?

sim*_*sjo 8 c# enums bitflags

编辑:似乎大多数人误解了我的问题.

我知道枚举是如何运作的,我知道二进制.我想知道为什么带有[Flags]属性的枚举是按原样设计的.

原帖:

这可能是重复的,但我没有找到任何其他帖子,所以这里.

我打赌它背后有一些很好的理由,我发现它有点容易出错.

[Flag]
public enum Flagged
{
  One, // 0
  Two, // 1
  Three, // 2
  Four, // 3
}

Flagged f; // Defaults to Flagged.One = 0
f = Flagged.Four;
(f & Flagged.One) != 0; // Sure.. One defaults to 0
(f & Flagged.Two) != 0; // 3 & 1 == 1
(f & Flagged.Three) != 0; // 3 & 2 == 2
Run Code Online (Sandbox Code Playgroud)

如果做到这样的话会不会更有意义?

[Flag]
public enum Flagged
{
  One = 1 << 0, // 1
  Two = 1 << 1, // 2
  Three = 1 << 2, // 4
  Four = 1 << 3, // 8
}

Flagged f; // Defaults to 0
f = Flagged.Four;
(f & Flagged.One) != 0; // 8 & 1  == 0
(f & Flagged.Two) != 0; // 8 & 2 == 0
(f & Flagged.Three) != 0; // 8 & 4 == 0
(f & Flagged.Four) != 0; // 8 & 8 == 8
Run Code Online (Sandbox Code Playgroud)

当然..我不太确定它应该如何处理这样的自定义标志

[Flag]
public enum Flagged
{
   One, // 1
   Two, // 2
   LessThanThree = One | Two,
   Three, // 4? start from Two?
   LessThanFour = Three | LessThanThree,
   Three, // 8? start from Three?
}
Run Code Online (Sandbox Code Playgroud)

该规范提供了一些指导

定义2的幂的枚举常量,即1,2,4,8等.这意味着组合枚举常量中的各个标志不重叠.

但这应该是自动完成的,因为我打赌你永远不会想要我的第一个例子.请赐教:)

Bri*_*sen 12

Flags属性仅用于将值格式化为多个值.位操作适用于具有或不具有该属性的基础类型.


Jef*_*tes 7

除非明确给出其他值,否则枚举的第一项为零.通常最佳做法是为标志枚举设置零值,因为它为零值提供了语义含义,例如"无标志"或"关闭".这有助于维护代码,因为它可能意味着代码的意图(尽管注释也实现了这一点).

除此之外,您和您的设计是否取决于您是否需要零值.

由于标志枚举仍然只是枚举(FlagsAttribute仅指示调试器将值解释为其他值的组合),因此枚举中的下一个值总是比前一个值多一个.因此,您应明确指定位值,因为您可能希望将组合表示为其他值的按位或.

也就是说,想象一个标志枚举的语法,要求所有按位组合放在枚举定义的末尾或以某种方式标记,这样编译器就知道如何处理其他所有内容,这并不是不合理的.

例如(假设一个flags关键字,我们在北半球),

flags enum MyFlags
{
   January,
   February,
   March,
   April,
   May,
   June,
   July,
   August,
   September,
   October,
   November,
   December,
   Winter = January | February | March
   Spring = April | May | June
   Summer = July | August | September
   Autumn = October | November | December
} 
Run Code Online (Sandbox Code Playgroud)

使用此语法,编译器可以自己创建0值,并自动为其他值分配标志.


BC.*_*BC. 6

属性是[Flags]而不是[Flag],并没有什么神奇之处.它似乎唯一影响的是ToString方法.指定[标志]时,值以逗号分隔.由您指定值以使其在位字段中有效.