11

以下代码块中的含义是什么if ((a & b) == b)

if ((e.Modifiers & Keys.Shift) == Keys.Shift)
{
    lbl.Text += "\n" + "Shift was held down.";
}

为什么不是这样?

if (e.Modifiers == Keys.Shift)
{
    lbl.Text += "\n" + "Shift was held down.";
}
4

8 回答 8

17

如果你看一下Keysenum,这是带有属性的标志枚举。[FlagsAttribute]

仅当要对数值执行按位运算(AND、OR、EXCLUSIVE OR)时,才对枚举使用 FlagsAttribute 自定义属性。

以 2 的幂定义枚举常数,即 1、2、4、8 等。这意味着组合枚举常量中的各个标志不重叠。

所以e.Modifiers可能是多个枚举的组合:

e.Modifiers = Keys.Shift | Keys.Cancel | Keys.Enter

只是非常简单的假设来解释这个概念:

Keys.Shift  : 001 (1)
Keys.Cancel : 010 (2)
Keys.Enter  : 100 (4)

所以:

e.Modifiers = Keys.Shift | Keys.Cancel | Keys.Enter equal 001 | 010 | 100 = 111

和条件:

    e.Modifiers & Keys.Shift equal 111 & 001 = 001

它的意思是:

 e.Modifiers & Keys.Shift == Keys.Shift

如果e.Modifiers不包含Keys.Shift

e.Modifiers = Keys.Cancel | Keys.Enter (110)

所以结果将是:

e.Modifiers & Keys.Shift equals 110 & 001 = 000 (is not Keys.Shift)

总而言之,这个条件检查是否e.Modifiers包含Keys.Shift

于 2013-04-17T15:10:29.880 回答
5

这是布尔逻辑(& =“按位与”)。您检查变量是否包含值。这就像一个过滤器。

例子:

a   -> 00110011
b   -> 00000011
a&b -> 00000011

在您的代码中

if ((e.Modifiers & Keys.Shift) == Keys.Shift)

检查 Keys.Shift 是否包含在 e.Modifiers 中。

于 2013-04-17T15:06:12.427 回答
4

一个 & 符号是指按位 AND 运算符。当与具有[Flags]属性的枚举结合使用时,Keys枚举确实如此,它用于确定是否设置了该枚举的位之一。

可能同时按下了多个修饰键,这就是为什么使用它而不是直接比较的原因。

您可以在此处阅读有关枚举标志的更多信息。向下滚动到标题为“作为位标志的枚举类型”的小节。您将看到与此非常相似的示例。

于 2013-04-17T15:06:17.700 回答
3

一个与号 (&) 是按位与,所以它基本上是将 (a & b) 的值相加,然后测试 (a & b) == b 中的相等性

因此,在您的示例中,基本上是说是否按下了 shift 键(任意键 + shift)== shift。

于 2013-04-17T15:05:32.150 回答
3

它使用按位运算来查询是否设置了“标志”(位)(等于 1)。

可能最好在http://msdn.microsoft.com/en-us/library/vstudio/cc138362.aspx上阅读枚举和按位运算

于 2013-04-17T15:07:03.640 回答
3

&是按位与运算符。它所做的Keys是一个标志枚举,其中的值Keys可以是几个值的按位组合。因此,要测试任何特定值,您首先将您的值与您要测试的值相比较,然后将其与您要测试的值进行比较。

例如,您可能同时按住 shift 和 ctrl 键,因此 in 的值e.Modifier将是Keys.Shiftand的按位组合Keys.Ctrl。所以这:

e.Modifier == Keys.Shift

是假的。Shift 被按住,但 Ctrl 也被按住。如果您想知道 Shift 是否被按住而不管其他键可能被按住,您需要首先过滤掉所有其他键。这很容易通过Keys.Shift用作过滤器来完成:

(e.Modifier & Keys.Shift) == Keys.Shift

现在,如果按住 shift 键而不管其他键可能被按下,这将是正确的,否则将是错误的。

于 2013-04-17T15:07:12.953 回答
3

第1部分

这是逻辑与运算符。

当多个标志应该在一个中设置时使用它,例如整数:

例如,a 是 3,表示二进制的 00000011。b 例如是 2,表示二进制的 00000010。

当您想检查 a 是否具有 b 代表设置的标志(右起第二位)时,您可以使用 AND 运算符:

a & b = 00000010

当它等于 b(或大于 0)时,您知道该标志已设置。

第2部分

相等运算符也可用于您要检查“Keys.Shift”是否是唯一的“修饰符”键并且没有按下其他键的情况。当您使用第一个代码时,也可以按下其他“修饰符”键,并且 if 条件仍然为真。

于 2013-04-17T15:07:23.867 回答
3

单个与号 (&) 执行按位与运算;双与号 (&&) 执行布尔 AND 运算。

逐位并对两个参数的每一位执行 AND 运算(因此称为“逐位”)。因此,按位与运算(或任何按位运算)的输出将不是布尔值。以下是按位与运算的一些示例:

1001 & 0001 = 0001
1101 & 1111 = 1101

布尔 AND 对两个布尔值进行运算并返回一个布尔值:

true && true = true
false && true = false

短路
也可以对两个返回布尔值的表达式执行布尔 AND 运算 (&&):

int a = 5;
int b = 10;
bool result = (a < 3) && (b > 3);
// result will be false;

因为第一个表达式的(a < 3)计算结果是false,所以结果不可能是true,因为两个表达式都必须计算true结果才能是true。因此,甚至不会计算第二个表达式。这称为“短路”。但是,对于按位与运算,两个表达式都需要在执行运算之前进行计算。因此,在大多数情况下,您只想确定两件事是否为真(布尔值),布尔值 AND (&&) 将是最佳选择。

在您的示例中,代码将内部e.Modifiers的各个位与Keys.Shift. 两个参数都不代表布尔值,因此操作是按位 (&) 而不是布尔值 (&&)。

于 2013-04-17T15:09:53.877 回答