Multiple ways to define C# Enums with [Flags] attribute?

自闭症网瘾萝莉.ら 提交于 2019-12-05 07:54:07

The main advantage with the first one is that you don't need to calculate the correct values for each flag since the compiler will do it for you. Apart from that they are the same.

Consider more complex samples:

[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
}

This samples shows that in this case first version is MUCH MORE readable. Decimal literals is not the best way to represent flag constants. And for more information about bitwise operations (that also can be used to represent flag constants) see http://en.wikipedia.org/wiki/Bitwise_operation

AFAIK its a readability debate. Some would say the first is more readable because you have the actual index of the flag on the right hand side of the '<<'.

There is another way to do this which is rather elegant and so I thought I'd share something I recently wrote. It has the benefit of requiring very little math and so I think it's less error prone. It is very readable, IMHO.

[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
}

NOTE: Since the enumeration inherits from System.Int32, I can only define 32 flags. If you need more you will have to use a larger integer (System.Int64), create more than one enumeration and chain them together, or just create a class with a bunch of boolean values.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!