23

I have this scenario where user has its role

NormalUser
Custodian
Finance

both Custodian and Finance is a SuperUser

How can i check if a role Custodian is a SuperUser

this is my sample code..

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    public enum Role
    {
        NormalUser = 0,
        Custodian = 1,
        Finance = 2,
        SuperUser = Custodian | Finance,
        All = Custodian | Finance | NormalUser
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Normal: " + Convert.ToInt32(Role.NormalUser));            
            Console.WriteLine("Custodian: " + Convert.ToInt32(Role.Custodian));
            Console.WriteLine("Finance: " + Convert.ToInt32(Role.Finance));            
            Console.WriteLine("SuperUser: " + Convert.ToInt32(Role.SuperUser));
            Console.WriteLine("All: " + Convert.ToInt32(Role.All));

            Console.WriteLine();
            Console.WriteLine("Normal User is in All: {0}", Role.NormalUser == Role.All);
            Console.WriteLine("Normal User is not a SuperUser: {0}", Role.NormalUser != Role.SuperUser);
            Console.WriteLine("Normal User is not a Custodian: {0}", Role.NormalUser != Role.Custodian);

            Console.WriteLine();
            Console.WriteLine("Custodian is in All: {0}", Role.Custodian == Role.All);
            Console.WriteLine("Custodian is a SuperUser: {0}", Role.Custodian == Role.SuperUser);
            Console.WriteLine("Custodian is a NormalUser: {0}", Role.Custodian == Role.NormalUser);

            Console.WriteLine();
            Console.WriteLine("Finance is in All: {0}", Role.Finance == Role.All);
            Console.WriteLine("Finance is a SuperUser: {0}", Role.Finance == Role.SuperUser);
            Console.WriteLine("Finance is a NormalUser: {0}", Role.Finance == Role.NormalUser);

            Console.ReadLine();
        }
    }
}

and this is the result if we run it

Normal: 0
Custodian: 1
Finance: 2
SuperUser: 3
All: 3

Normal User is in All: False
Normal User is not a SuperUser: True
Normal User is not a Custodian: True

Custodian is in All: False
Custodian is a SuperUser: False
Custodian is a NormalUser: False

Finance is in All: False
Finance is a SuperUser: False
Finance is a NormalUser: False

i am expecting that a

Custodian is in All: True,
Custodian is a SuperUser: True,
Finance is in All: True,
Finance is a SuperUser: True,
Normal User is in All: True

2

4 Answers 4

66

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.

Sign up to request clarification or add additional context in comments.

2 Comments

What is reason for spaced out by powers of 2 values. I know that is how you are supposed to do it but not sure as why?
@DonO just updated answer to include explanation of why powers of 2 are used, it was a little big to cover in a comment. Hopefully it's useful / makes sense.
23

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

Comments

2

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
 }

1 Comment

You still need to use powers of two. Otherwise it won't work. That's in the documentation: learn.microsoft.com/en-us/previous-versions/dotnet/…
2

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

3 Comments

I dont get why. Isnt a & b == c just a == c && b == c? If so, why not a == c? Your Role.All looks wrong in here for me. Not saying your are wrong. Just saying I cant get why...
@C4d a & b == c is not a == c && b == c! See 0b01 & 0b10 == 0b00. The & is a bit operation and doesn't mean a and b are equal to c.
@Darkproduct Nearly 8 years later I get nostalgic feelings looking at a comment from my younger/junior self who had no idea what bitwise operations were lol.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.