位运算 - 检查和删除

Bitwise operations - checking and removal

注意下面的简单示例:

Module Module1
    <Flags>
    Public Enum Names
        None    = 0
        Test    = 1
        Test2   = 2
        Test3   = 4
        Test4   = 8
    End Enum

    Sub Main()
        Dim test As Names = Names.Test Or Names.Test3
        If (test And Names.Test3) = Names.Test3
            Console.WriteLine("TRUE")
        Else
            Console.WriteLine("FALSE")
        End If
    End Sub
End Module

我问题的第一部分与行 If (test And Names.Test3) = Names.Test3.

有关

如果标志存在,直接检查 If test And Names.Test3 不是更好吗?如果它的计算结果为非零值(意味着标志存在),那么条件的结果无论如何都是 True

使用第一种方法检查第二种方法是否有充分的理由? (虽然我的回答是针对 VB.NET,但我也很想知道这是否是其他任何地方的潜在陷阱,即 C#、C++ 等)。

此外,关于移除标志,似乎有两种方法可以做到这一点:

test = test Xor Names.Test3test = test And Not Names.Test3

但是,第一个会在缺少标志时添加标志,如果存在则将其删除,而第二个只会删除它。这是唯一的区别吗?还是我更喜欢一种方法而不是另一种方法的另一个原因?

你说你可以有效地替换这个是正确的:

If (test And Names.Test3) = Names.Test3 Then

有了这个

If (test And Names.Test3) Then

但是,第二个例子不会用Option Strict On编译,因为你正确地得到了错误:

Option Strict On disallows implicit conversions from 'Names' to 'Boolean' 所以为了编译它你需要用 CBool 包裹它。

因此,总而言之,我会说使用第一个示例要好得多,因为意图非常明确:- 您正在检查是否设置了某个位。

就标志删除而言,即取消设置,您应该使用:

test = test And Not Names.Test3

使用 Xor 具有 切换 值的效果。

以下内容可能会有所帮助(尤其是当您制作扩展方法时):

Public Function SetBit(ByVal aValue As Names, ByVal aBit As Names) As Names
    Return (aValue Or aBit)
End Function

Public Function ClearBit(ByVal aValue As Names, ByVal aBit As Names) As Names
    Return (aValue And Not aBit)
End Function

Public Function IsBitSet(ByVal aValue As Names, ByVal aBit As Names) As Boolean
    Return ((aValue And aBit) = aBit)
End Function

Public Function ToggleBit(ByVal aValue As Names, ByVal aBit As Names) As Names
    Return (aValue Xor aBit)
End Function

请记住,Flags 枚举不一定都是纯粹的单位值。例如。想象一下(用更好的名字)你的枚举是:

<Flags>
Public Enum Names
    None    = 0
    Test    = 1
    Test2   = 2
    Test3   = 4
    Test4   = 8
    Test2AndTest4 = 10
End Enum

现在,您不想只测试 test And Names.Test2AndTest4 是否为非零,因为这不能回答正确的问题。因此,一般来说,养成 And 您的掩码进行检查然后与掩码值进行比较是一个更好的习惯,以确保掩码的 所有 位都已设置.