以下代码块中的含义是什么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.";
}
以下代码块中的含义是什么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.";
}
如果你看一下Keys
enum,这是带有属性的标志枚举。[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
这是布尔逻辑(& =“按位与”)。您检查变量是否包含值。这就像一个过滤器。
例子:
a -> 00110011
b -> 00000011
a&b -> 00000011
在您的代码中
if ((e.Modifiers & Keys.Shift) == Keys.Shift)
检查 Keys.Shift 是否包含在 e.Modifiers 中。
一个 & 符号是指按位 AND 运算符。当与具有[Flags]
属性的枚举结合使用时,Keys
枚举确实如此,它用于确定是否设置了该枚举的位之一。
可能同时按下了多个修饰键,这就是为什么使用它而不是直接比较的原因。
您可以在此处阅读有关枚举标志的更多信息。向下滚动到标题为“作为位标志的枚举类型”的小节。您将看到与此非常相似的示例。
一个与号 (&) 是按位与,所以它基本上是将 (a & b) 的值相加,然后测试 (a & b) == b 中的相等性
因此,在您的示例中,基本上是说是否按下了 shift 键(任意键 + shift)== shift。
它使用按位运算来查询是否设置了“标志”(位)(等于 1)。
可能最好在http://msdn.microsoft.com/en-us/library/vstudio/cc138362.aspx上阅读枚举和按位运算
&
是按位与运算符。它所做的Keys
是一个标志枚举,其中的值Keys
可以是几个值的按位组合。因此,要测试任何特定值,您首先将您的值与您要测试的值相比较,然后将其与您要测试的值进行比较。
例如,您可能同时按住 shift 和 ctrl 键,因此 in 的值e.Modifier
将是Keys.Shift
and的按位组合Keys.Ctrl
。所以这:
e.Modifier == Keys.Shift
是假的。Shift 被按住,但 Ctrl 也被按住。如果您想知道 Shift 是否被按住而不管其他键可能被按住,您需要首先过滤掉所有其他键。这很容易通过Keys.Shift
用作过滤器来完成:
(e.Modifier & Keys.Shift) == Keys.Shift
现在,如果按住 shift 键而不管其他键可能被按下,这将是正确的,否则将是错误的。
第1部分
这是逻辑与运算符。
当多个标志应该在一个中设置时使用它,例如整数:
例如,a 是 3,表示二进制的 00000011。b 例如是 2,表示二进制的 00000010。
当您想检查 a 是否具有 b 代表设置的标志(右起第二位)时,您可以使用 AND 运算符:
a & b = 00000010
当它等于 b(或大于 0)时,您知道该标志已设置。
第2部分
相等运算符也可用于您要检查“Keys.Shift”是否是唯一的“修饰符”键并且没有按下其他键的情况。当您使用第一个代码时,也可以按下其他“修饰符”键,并且 if 条件仍然为真。
单个与号 (&) 执行按位与运算;双与号 (&&) 执行布尔 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
. 两个参数都不代表布尔值,因此操作是按位 (&) 而不是布尔值 (&&)。