2

我想知道以下枚举掩码是如何工作的

如果我有一个枚举结构

public enum DelMask
{
        pass = 1,       
        fail = 2,       
        abandoned = 4,        
        distinction = 8,             
        merit = 16,        
        defer = 32,        
}

我看过下面的代码

int pass = 48;
if ((pass & (int)DelMask.defer) > 0)
   //Do something
else if ((pass & (int)DelMask.merit ) > 0)
   //Do something else

我想知道谁能帮我弄清楚哪个块将如何执行?

4

5 回答 5

3

在这里工作的基本位逻辑。整数 48 以二进制结尾:

0011 0000

32 岁的延迟是:

0010 0000

16岁的优点是:

0001 0000

现在,当您执行逻辑与 (&) 时,结果位将设置在它们都在输入中的位置:

pass & (int)DelMask.defer

0011 0000 
0010 0000
========= & 
0010 0000    

结果将是 16,因此((pass & (int)DelMask.defer) > 0)将评估为真。在您的示例中,两者if都将评估为 true,因为输入中都存在两个标志。第二个不会被评估,因为它是一个else if.

于 2012-11-01T11:15:31.707 回答
1

两者都是正确的,因此第一个将被执行。

16 是 10000

32 是 100000

48 是 16+32 所以是 110000

10000 & 110000 是 10000

100000 & 110000 是 100000

两者都大于零。

于 2012-11-01T11:13:41.183 回答
1

48 = 16(优异)+ 32(延期)。

因此pass & (int)DelMask.defer评估为 32,因此第一个块运行。

如果不是这种情况,则pass & (int)DelMask.merit计算结果为 16,因此如果达到那么远,第二个块将运行。

这只有效,因为枚举中的值都是 2 的不同幂,因此对应于底层的独立位int。这就是所谓的位标志枚举。

于 2012-11-01T11:14:34.517 回答
1

首先,它应该是int pass = 48; 基本上这段代码检查是否在数字的二进制表示中设置了一个位。每个 & 操作都应该在掩码中的位置产生一个全为零和一个的结果。例如:

48:         110000
defer = 32: 100000
            ______
          & 100000

所以你可以使用这个代码:

int pass = 48;
if ((pass & (int)DelMask.defer) == (int)DelMask.defer)
   //Do something
else if ((pass & (int)DelMask.merit ) == (int)DelMask.merit)
   //Do something else
于 2012-11-01T11:15:09.977 回答
1

好吧,您需要将这些数字视为二进制。我将使用 d 后缀来显示十进制表示法,使用 b 后缀表示二进制表示法。

枚举值:

  • 01d = 000001b
  • 02d = 000010b
  • 04d = 000100b
  • 08d = 001000b
  • 16d = 010000b
  • 32d = 100000b

传递值:

48d = 110000b

现在&是按位与运算符。这意味着如果 c = a&b,当且仅当 a 和 b 中的第 n 位为 1 时,c 中的第 n 位将为 1。

所以:

  • 16d & 48d = 010000b = 16d > 0
  • 32d & 48d = 100000b = 32d > 0

如您所见,您的数字 48d 与 16d 和 32d “匹配”。这就是为什么这种枚举通常被描述为“标志”枚举的原因:您可以用一个整数获得多个“标志”的值。

至于您的代码,if将验证第一个运算符,这意味着您将输入它并“做某事”。你不会“做其他事情”。

通常在 C# 中,我们将[Flags] 属性用于标志枚举,它允许实际上不为枚举成员写入十进制值。像往常一样,MSDN 中的示例没用,所以我将参考这个SO question以了解有关如何使用它的更多详细信息(请注意,要知道值 x 是否设置了标志 f,您可以执行x & f == for x | f == x,但是用法似乎是一般使用后一种)。

于 2012-11-01T11:22:35.350 回答