if((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) { } 是如何工作的?

How does if((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) { } work?

this 页面上,我看到以下代码:

if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)

但是我不明白为什么会这样。

为什么attributes & FileAttributes.Hidden)attributes 上的单数检查实际上做了什么?它是否检查它是否不为空?我有一种感觉,我知道,但它看起来很奇怪。随机和奇怪。

这是简单的布尔逻辑。如果双方具有完全相同的值,则 == 运算符仅 returns true。因此,您必须 mask attributes 值与您要比较的标志。考虑这两个例子(值是组成的):

正确:

  0010001 // attributes
& 0000001 // FileAttributes.Hidden
  -------
= 0000001 // FileAttributes.Hidden

错误:

  0011000 // attributes
& 0000001 // FileAttributes.Hidden
  -------
= 0000000 // FileAttributes.None

& 是按位与运算符。

此运算符仅对 2 组位执行按位与运算。

0 & 0 === 0
1 & 0 === 0
0 & 1 === 0
1 & 1 === 1

在 and 运算符旁边,还有一个 OR (|) 和 XOR(异或)(^) 运算符。

attributesFileAttributes 类型。此类型是 enum,一种值类型。它不是 FileAttributes? (Nullable<FileAttributes>),所以它 不能为 null

每个 enum 都包含一个命名值列表,但每个值都是 mappable/convertible 一些整数 (int) 值。在许多地方,C# 允许您 "exploit" 该转换并(在某种程度上)将枚举值视为整数,但它们仍然不是。

例如,& 运算符执行您所期望的 - 它执行二进制 AND。这样,如果转换为整数的枚举值设置了相关位,您将得到一些非零结果。

在检查 flags/bits 是否存在于某些状态值的 "good old way" 中。您可能经常看到像 foo & FLAG != 0 这样的表达式,它检查标志是否已设置,或 foo & (FLAG|BLAG) != 0 检查这两个中的任何一个是否被设置。这有点 flawed/dangerous 因为如果有人将 FLAG 更改为不止一位,那么这样的表达式将检查是否设置了任何位,而不是检查整个 "multi-bit flag" 是否已设置。这就是为什么您可能还经常看到 foo & FLAG == FLAG 应用位掩码并检查结果是否是位掩码,因此它检查是否设置了掩码的所有位。

在这里,你的情况就是这样。由于在该表达式中您使用相同的掩码进行 ANDing 和 COMPARING,因此您实际上是在检查是否设置了掩码的所有位。但这是多余的,因为 FileAttributes 明确标记为 [Flags],Hidden 值只有一位,所以 != 0 就足够了。

然而,在这种情况下(检查标志,而不是花哨的按位掩码)你可以尝试使用 Enum.HasFlag 方法,大多数人会建议你使用它,因为它是为这种情况设计的;)

但这并不总是最佳选择。请看:

..但如果性能成本对您来说是个问题,我会感到惊讶。很少需要优化到这一点。