Combining Enum Values with Bit-Flags

后端 未结 4 1570
傲寒
傲寒 2021-02-13 04:43

I have this scenario where user has its role

NormalUser
Custodian
Finance

both Custodian and Finance is a Super

相关标签:
4条回答
  • 2021-02-13 05:22

    I think this might be a duplicate of How do you pass multiple enum values in C#?

    Where the & bitmask can do the trick.

    ((Role.NormalUser & Role.All) == Role.NormalUser)
    

    Inspecting this closer you will get the following:

    0b0 & 0b11 == 0b0
    

    However if you lets say want to check if the SuperUser is in finance you will get the following:

    ((Role.SuperUser & Role.Finance) == Role.Finance)
    

    This will evaluate to:

    0b11 & 0b10 == 0b10
    
    0 讨论(0)
  • 2021-02-13 05:29

    You can add the Flag-attribute to the Enum

    [Flags]
    public enum Role
    {
        NormalUser,
        Custodian,
        Finance,
        SuperUser = Custodian | Finance,
        All = Custodian | Finance | NormalUser
    }
    

    Then you can check for a role with this expression:

     Role testRole = Role.Finance
     if(testRole & Role.SuperUser == Role.SuperUser){
          //testRole is SuperUser
     }
    
    0 讨论(0)
  • 2021-02-13 05:39

    Check out What does the [Flags] Enum Attribute mean in C#? for a more thorough explanation.

    A "safer" way to declare flags is to use bit-shifting to ensure there's no overlap (as mentioned by @DaveOwen's answer) without figuring out the math yourself:

    [Flags]
    public enum MyEnum
    {
        None   = 0,
        First  = 1 << 0,
        Second = 1 << 1,
        Third  = 1 << 2,
        Fourth = 1 << 3
    }
    

    There's also Enum.HasFlag (possibly newer .NET than OP) for checking, rather than Expected & Testing == Expected

    0 讨论(0)
  • 2021-02-13 05:42

    Enum.HasFlag is what you want to use

    Console.WriteLine("Custodian is in All: {0}", Role.All.HasFlag(Role.Custodian));
    

    Just noticed that your enum should be defined like this with the Flags attribute and values spaced out by powers of 2

    [Flags]
    public enum Role
    {
        NormalUser = 1,
        Custodian = 2,
        Finance = 4,
        SuperUser = Custodian | Finance,
        All = Custodian | Finance | NormalUser
    }
    

    The reason powers of 2 are used for flagged enums is that each power of 2 represents a unique bit being set in the binary representation:

    NormalUser = 1 = 00000001
    Custodian  = 2 = 00000010
    Finance    = 4 = 00000100
    Other      = 8 = 00001000
    

    Because each item in the enum has a unique bit set this allows them to be combined by setting their respective bits.

    SuperUser  = 6 = 00000110 = Custodian + Finance
    All        = 7 = 00000111 = NormalUser + Custodian + Finance
    NormOther  = 9 = 00001001 = NormalUser + Other
    

    Notice how each 1 in the binary form lines up with the bit set for the flag in the section above.

    0 讨论(0)
提交回复
热议问题