How do I retrieve a value from a [Flag] enum property? [duplicate]
Asked Answered
S

2

9

Say I have an enum defined like so:

[Flags]
public enum LogLevel
{
    None = 1,
    Pages = 2,
    Methods = 4,
    Exception =8
}

and a class like:

public static class Log
{
    public static LogLevel Level = LogLevel.Methods | LogLevel.Pages;

    public static void EnterPage([CallerFilePath]string filePath = "")
    {
        if (Level == //What value here to check if Level includes Pages?)
        {
             //Log
        }
    }

What value do I need to equate Level to to check whether the enum includes Pages?

Salute answered 20/11, 2015 at 14:12 Comment(1)
See #8947Analyzer
S
9

First of all, flags must have a None = 0 value, because otherwise there's no way to represent a 0 mask (i.e. no value).

Once you've fixed it, you can check if some enumeration value is in some given flag using Enum.HasFlag or the bit-wise & operator:

Level.HasFlag(LogLevel.Pages);

...or:

(Level & LogLevel.Pages) == LogLevel.Pages

Finally, when you implement a flags enumeration, usually enumeration identifier is expressed in plural. In your case, you should refactor LogLevel to LogLevels.

Why &?

Each enumeration value represents a bit in a complete mask. For example, None would be 0, but it could be also represented as 0, 0, 0 where each 0 is one of possible enumeration values in LogLevels. When you provide a mask like LogLevels.Pages | LogLevels.Methods, then the mask is 1, 1, 0.

In order to check if Pages is within the mask, you use a logical AND comparing the mask with one of possible enumeration values:

1, 1, 0 (LogLevels.Pages | LogLevels.Methods)
1, 0, 0 AND (LogLevels.Pages)
--------
1, 0, 0 
  • 1 and 1 (true and true == true)
  • 1 and 0 (true and false == false)
  • 0 and 0 (false and false == false).

The whole AND is like isolating the tested enumeration value. If the resulting mask equals the enumeration value, then the mask contains the enumeration value.

Some OP concern

OP said in some comment:

Just a quick question on zero value. here it states that You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. Does that mean if I have a 0 value I cannot use & and must use HasFlag?

None (i.e. 0) won't be a member of a mask, because 0 doesn't exist. When you produce a mask you're using the OR | logical operator, which is, at the end of the day, an addition.

Think about 1 + 0 == 1. Would you think checking if 0 is within 1 is ever possible?

Actually, the None = 0 value is required to be able to represent and empty mask.

Finally, HasFlag does the AND for you, it's not a magical solution, but a more readable and encapsulated way of performing the so-called AND.

Stegodon answered 20/11, 2015 at 14:16 Comment(0)
I
0

like this

if (Level.HasFlag(LogLevel.Pages))
{             
   //todo  
}
Innutrition answered 20/11, 2015 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.