.NET enum.HasFlag() 错误?

.NET enum.HasFlag() bug?

我正在使用以下 .NET 4.5.2 代码:

if (this.ContainsFocus && keyData == (Keys.Tab|Keys.Shift))
{ ... }

为什么当ContainsFocus (bool = true) 和keyData (System.Windows.Forms.Keys) 为Keys.O 时表达式为真 | Keys.Shift?

如您所见,命中断点:

具有以下值:

此错误 (?!) 的解决方法是:

if (this.ContainsFocus && (int)keyData == (int)(Keys.Tab|Keys.Shift))
{ ... }

这不是 HasFlag 的错误,而是它的工作原理。
假设我们有以下值:

var a = (Keys.Tab | Keys.Shift);
var b = (Keys.O | Keys.Shift);

现在我们分析这些值的位(当我们将它们转换为整数时):

a: 10000000001000001
b: 10000000001001111

如果我们调用 a.HasFlag(b),我们会得到 false,因为并非 b 中的每个 1 位都是 a[= 中的 1 32=]也是。但是如果我们调用 b.HasFlag(a) 我们会得到 true 因为 a 的每个 1 位也在 b 中设置。

这就是为什么您需要将值与 a==ba.HasFlag(b) && b.HasFlag(a) 进行比较的原因。然后就可以正常使用了。

不,HasFlag 没有错误。不幸的是,.NET FlagsAttribute 是全有或全无,并且 System.Windows.Forms.Keys 的定义方式使得只有 Keys.Modifiers 可以用作标志。

来自https://msdn.microsoft.com/en-us/library/system.windows.forms.keys%28v=vs.110%29.aspx

The Keys class contains constants for processing keyboard input. The members of the Keys enumeration consist of a key code and a set of modifiers combined into a single integer value. In the Win32 application programming interface (API) a key value has two halves, with the high-order bits containing the key code (which is the same as a Windows virtual key code), and the low-order bits representing key modifiers such as the SHIFT, CONTROL, and ALT keys.

因此,您可以使用 HasFlag 检查任何修饰符(Keys.ShiftKeys.AltKeys.Control),但不能检查其他任何修饰符。