关于C#:如何从[flag]枚举属性中检索值?

How do I retrieve a value from a [Flag] enum property?

本问题已经有最佳答案,请猛点这里访问。

假设我有一个enum定义如下:

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

以及一个类,比如:

1
2
3
4
5
6
7
8
9
10
11
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
        }
    }

为了检查枚举是否包括Pages,需要将Level等同为什么值?


首先,标志必须有一个None = 0值,否则就无法表示0掩码(即没有值)。

修复后,可以使用Enum.HasFlag或按位&运算符检查某个给定标志中是否存在某些枚举值:

1
Level.HasFlag(LogLevel.Pages);

…或:

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

最后,在实现标志枚举时,通常枚举标识符以复数形式表示。在您的情况下,您应该将LogLevel重构为LogLevels

为什么是&

每个枚举值表示完整掩码中的一位。例如,None为0,但也可以表示为0, 0, 0,其中每个0LogLevels中可能的枚举值之一。当你提供一个像LogLevels.Pages | LogLevels.Methods这样的面具时,这个面具就是1, 1, 0

为了检查Pages是否在掩码内,可以使用逻辑和比较掩码与可能的枚举值之一:

1
2
3
4
1, 1, 0 (LogLevels.Pages | LogLevels.Methods)
1, 0, 0 AND (LogLevels.Pages)
--------
1, 0, 0
  • 1和1(真和真=真)
  • 1和0(真和假=假)
  • 0和0(假和假=假)。

整个,就像隔离测试的枚举值。如果生成的掩码等于枚举值,则该掩码包含枚举值。

一些关注点

OP在评论中说:

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?

因为0不存在,所以None(即0不属于掩码的成员。当您生成一个蒙版时,您使用的是或|逻辑运算符,在一天结束时,这是一个加法。

想想1 + 0 == 1。你认为检查0是否在1内是可能的吗?

实际上,需要None = 0值来表示和清空掩码。

最后,HasFlag为你做了AND,这不是一个神奇的解决方案,而是一种更可读、更封装的执行所谓AND的方式。


这样地

1
2
3
4
if (Level.HasFlag(LogLevel.Pages))
{            
   //todo  
}