C# 枚举类型与 Flags 属性

10

我想知道带有标记属性的枚举类型大多用于按位运算,为什么编译器不会在未定义枚举值时自动生成值。

例如:

[Flags]
public enum MyColor
{
    Yellow = 1,
    Green = 2,
    Red = 4,
    Blue = 8
}

如果未分配这些值,自动生成1、2、4和8将会很有帮助。希望了解您的想法。

4个回答

13

这个稍微容易一些:

[Flags]
public enum MyColor
{
    Yellow = 1<<0,
    Green = 1<<1,
    Red = 1<<2,
    Blue = 1<<3
}

它可以帮助您节省计算下一个可用值的时间。 - Ofir
1<<0 的伪英语是什么? - Preston McCormick
1
左移零位的一位比特 - Dan Byström

3
他们可能可以这样做,但是考虑到实现某些功能所需的时间和资源与潜在的收益,特别是对于这样一个庞大的编译器,他们需要谨慎权衡。而且这只是语法糖,因为你也可以手动编写它。

3
我认为这是由于FlagsAttribute实例正在与Enum一起编译或之后编译。换句话说,使用属性(如[Flags])装饰对象会导致创建属性对象,而不是对基本对象进行根本性修改。
此外,存储的部分信息(用于运行时实例化属性)是它所引用的实体。可能是枚举实体必须在其属性之前编译,因此属性无法影响它引用的实体(在本例中为枚举)。我不知道这个陈述是否正确,这只是一个猜测。
最重要的是,像[Flags]这样的属性实际上是实体本身,而不是修饰类型的修改。

2

我认为,这主要归结于第一个值的巨大混乱。请考虑以下情况:

[Flags]
public enum MyColor
{
    Yellow,
    Green,
    Red,
    Blue
 }

public class SomeClass
{
  public MyColor SomeColor;  // Yellow or undefined by default?
}

当一个类被实例化时,通常情况下它的所有字段都被清零(引用变为null,值变为零)。但是如果第一个值是1,则编译器必须与其他任何东西不同地处理Flag枚举。
因此,考虑到这一点,以及能够将位字段清零非常有用,我们得出结论,第一个字段实际上应该逻辑上为零:
[Flags]
public enum MyColor
{
    Black,   //0
    Yellow,  //1
    Green,   //2
    Red,     //3
    Blue     //4
}

但我猜很少有人会意识到这一点(没有上面的评论)。而且还会出现更棘手的问题:

[Flags]
public enum MyColor
{
    Black,
    Red,
    Green,
    Blue,
    Magenta = Red | Blue,
    Yellow = Red | Green | Blue,
    SomeOtherColor  // now what would the value of this automatically be?
}

最好明确说明以避免混淆! :-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接