如何从 [Flag] 枚举 属性 中检索值?

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

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

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

和 class 喜欢:

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

我需要将 Level 等同于什么值来检查枚举是否包含 Pages

像这样

if (Level.HasFlag(LogLevel.Pages))
{             
   //todo  
}

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

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

Level.HasFlag(LogLevel.Pages);

...或:

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

最后,当你实现一个flags枚举时,枚举标识符通常用复数表示。在您的情况下,您应该将 LogLevel 重构为 LogLevels.

为什么 &

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

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

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

整个AND就像把被测试的枚举值孤立起来一样。如果生成的掩码等于枚举值,则掩码包含枚举值。

一些 OP 问题

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?

None(即 0)不会成为掩码的成员,因为 0 不存在 。当您生成掩码时,您使用的是 OR | 逻辑运算符,归根结底,这是一个加法。

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

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

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