按位操作 - 检查和删除

时间:2016-07-05 10:27:09

标签: vb.net bitwise-operators bitwise-and bitwise-xor

请注意以下简单示例:

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

但是,第一个会在缺少标记的情况下添加标记,如果存在则删除标记,而第二个标记只删除标记。这是唯一的区别吗?或者是否有另一个原因我应该选择一种方法而不是另一种方法?

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

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

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

现在,您不希望仅测试test And Names.Test2AndTest4非零,因为它没有回答正确的问题。因此,一般来说,进入And掩码进行检查然后与掩码值进行比较是一种更好的习惯,以确保设置掩码的所有位。