请注意以下简单示例:
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.Test3
和test = test And Not Names.Test3
但是,第一个会在缺少标记的情况下添加标记,如果存在则删除标记,而第二个标记只删除标记。这是唯一的区别吗?或者是否有另一个原因我应该选择一种方法而不是另一种方法?
答案 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
掩码进行检查然后与掩码值进行比较是一种更好的习惯,以确保设置掩码的所有位。