使用[Flags]属性定义C#枚举的多种方法?

时间:2010-01-25 17:29:59

标签: c# .net enums flags

我理解Enums如何在C#中工作,并且我得到了Flags属性带来的内容。

我看到了这个问题,here。推荐第一种口味,但不提供任何理由/理由。

两者的定义方式是否存在差异,哪一个比另一个好?使用第一个synax代替第二个synax有什么好处?在定义Flags类型Enums时,我总是使用第二种风格......我一直都做错了吗?

[Serializable]
[Flags]
public enum SiteRoles
{
    User = 1 << 0,
    Admin = 1 << 1,
    Helpdesk = 1 << 2
}

这与

不一样
[Serializable]
[Flags]
public enum SiteRoles
{
    User = 1,
    Admin = 2,
    Helpdesk = 4
}

4 个答案:

答案 0 :(得分:6)

第一个的主要优点是您不需要为每个标志计算正确的值,因为编译器会为您执行此操作。除此之外,他们是一样的。

答案 1 :(得分:6)

考虑更复杂的样本:

[Flags]
public enum SiteRoles
{
    User = 1 << 12,
    Admin = 1 << 13,
    Helpdesk = 1 << 15,
    AdvancedUser = User | Helpdesk, //or (1<<12)|(1<<13)
}

[Flags]
public enum SiteRoles
{
    User = 4096, //not so obvious!
    Admin = 8192,
    Helpdesk = 16384,
    AdvancedUser = 12288, //!
}

[Flags]
public enum SiteRoles
{
    User = 0x1000, //we can use hexademical digits
    Admin = 0x2000,
    Helpdesk = 0x4000,
    AdvancedUser = 0x3000, //it much simpler calculate binary operator OR with hexademicals
}

此示例显示在这种情况下,第一个版本更具可读性。十进制文字不是表示标志常量的最佳方式。有关按位运算的更多信息(也可用于表示标志常量),请参阅http://en.wikipedia.org/wiki/Bitwise_operation

答案 2 :(得分:0)

AFAIK是一个可读性辩论。有人会说第一个更具可读性,因为你在'&lt;&lt;'的右侧有标志的实际索引。

答案 3 :(得分:0)

有另一种方法可以做到这一点相当优雅,所以我想我会分享我最近写的东西。它的好处是需要很少的数学,因此我认为它不易出错。它非常易读,恕我直言。

[Flags][Serializable]
public enum ScopeType : int
{
    Unknown = 0,
    Global = 1,
    Namespace = Global << 1,
    Class = Namespace << 1,
    Struct = Class << 1,
    Interface = Struct << 1,
    Enum = Interface << 1,
    Function = Enum << 1,
    Property = Function << 1,
    PropertyGetter = Property << 1,
    PropertySetter = PropertyGetter << 1,
    Using = PropertySetter << 1,
    If = Using << 1,
    ElseIf = If << 1,
    Else = ElseIf << 1,
    Switch = Else << 1,
    Case = Switch << 1,
    For = Case << 1,
    While = For << 1,
    DoWhile = While << 1,
    Lambda = DoWhile << 1,
    Try = Lambda << 1,
    Catch = Try << 1,
    Finally = Catch << 1,
    Initializer = Finally << 1,
    Checked = Initializer << 1,
    Unchecked = Checked << 1,
    Unsafe = Unchecked << 1,
    Lock = Unsafe << 1,
    Fixed = Lock << 1,

    // I can also group flags together using bitwise-OR.
    PropertyAccessor = PropertyGetter | PropertySetter,
    TypeDefinition = Class | Struct | Interface | Enum,
    TryCatchFinally = Try | Catch | Finally,
    Conditional = If | ElseIf | Else,
    Branch = Conditional | Case | TryCatchFinally,
    Loop = For | While | DoWhile
}

注意:由于枚举继承自System.Int32,因此我只能定义32个标志。如果您需要更多,则必须使用更大的整数(System.Int64),创建多个枚举并将它们链接在一起,或者只创建一个包含一堆布尔值的类。