按位值必须是指数的吗?

时间:2013-02-21 14:54:05

标签: .net bit-manipulation bitwise-operators

在所有按位示例中,我看到值以指数方式递增(1,2,4,8等)。但是,在下面的Enum中,我使用1,2,3,4(并且请原谅VB,如果你愿意的话):

<Flags()>
Enum BitWiseTest
    One = 1
    Two = 2
    Three = 3
    Four = 4
End Enum

令我惊讶的是,以下代码有效:

Dim TestBits As BitWiseTest

TestBits = TestBits Or BitWiseTest.One
TestBits = TestBits Or BitWiseTest.Two
TestBits = TestBits Or BitWiseTest.Three
TestBits = TestBits Or BitWiseTest.Four

Dim BitToRemove As BitWiseTest

BitToRemove = BitWiseTest.Two

TestBits = Not BitToRemove

Console.WriteLine(TestBits And BitToRemove)

注释掉TestBits = Not BitToRemove行会告诉您,不删除该位会显示它仍然存在。将BitToRemove = BitWiseTest.Two改为使用另一个枚举值将显示它对其他位有效。

它看起来工作得很完美,所以我在各处看到的按比例增加值的指数增量是什么?

3 个答案:

答案 0 :(得分:3)

  

它看起来完美无缺

这取决于你所说的“完美无瑕”。

真的希望BitWiseTest.OneBitwiseTest.Two等于BitwiseTest.Three吗?这就是你现在所能得到的,这通常不是理想的......通常你希望标志是独立的,这意味着它们需要用二进制表示中的独立位表示 - 这正是你得到的通过使用值1,2,4,8,16等

答案 1 :(得分:2)

通常有两种枚举。对于枚举:

  1. 使用其中一个值。
  2. 使用值的组合。
  3. 使用其中一个值

    在这种情况下,您可以按照自己喜欢的方式为枚举成员编号。如果它们的含义相同,您甚至可以拥有两个具有相同值的成员。例如:

    Enum Comparison
        None = 0
        CaseSensitive = 1
        IgnoreCase = 2
    
        Default = 1
    End Enum
    

    使用值的组合

    值现在为布尔值:它是 on (已使用,已指定)或 off (未使用或未指定)。这很好地转换为位,即1(开)或0(关)。为了能够区分这些值,您应该使用2的幂。然后,对于任何特定位,只有一个值可以将该位设置为打开或关闭。

    <Flags()>
    Enum NumberStyles
        None = 0                    ' Binary:          0
        AllowLeadingWhite = 1       ' Binary:          1
        AllowTrailingWhite = 2      ' Binary:         10
        AllowLeadingSign = 4        ' Binary:        100
        AllowTrailingSign = 8       ' Binary:       1000
        AllowParentheses = 16       ' Binary:      10000
        AllowDecimalPoint = 32      ' Binary:     100000
        AllowThousands = 64         ' Binary:    1000000
        AllowExponent = 128         ' Binary:   10000000
        AllowCurrencySymbol = 256   ' Binary:  100000000
        AllowHexSpecifier = 512     ' Binary: 1000000000
    End Enum
    

    现在,您可以组合两个值来获取新值,并且可以区分这些值:

    Dim testBits As NumberStyles
    testBits = NumberStyles.AllowHexSpecifier _
            Or NumberStyles.AllowTrailingWhite _
            Or NumberStyles.AllowLeadingWhite       ' Binary: 1000000011
    
    ' If (1000000011 And 1000000000) <> 0 Then
    If testBits.HasFlag(NumberStyles.AllowHexSpecifier) Then
        ' Do something
    End If
    

    如果有意义的话,你也可以将这些组合添加到枚举中:

    <Flags()>
    Enum NumberStyles
        ' ...
        Integer = 7                 ' Binary:        111
        Number = 111                ' Binary:    1101111
        Float = 167                 ' Binary:   10100111
        Currency = 383              ' Binary:  101111111
        HexNumber = 515             ' Binary: 1000000011
    End Enum
    

    关于您的示例

    查看示例的二进制值。值OneTwoFour是2的幂,但Three不是。<Flags()> Enum BitWiseTest One = 1 ' Binary: 1 Two = 2 ' Binary: 10 Three = 3 ' Binary: 11 Four = 4 ' Binary: 100 Five = 5 ' Binary: 101 Six = 6 ' Binary: 110 Seven = 7 ' Binary: 111 End Enum 。如果我扩展你的例子,也许你可以看到问题:

    Six Or Three = Seven

    现在,做value And Two,这通常不是你想要的。当TruevalueThreeSix时,Seven Two也是Three,现在也可能是您想要的。原因是Six中设置的一位也出现在Seven,{{1}}和{{1}}中,这取决于您选择值的方式。

答案 2 :(得分:0)

它们不一定是指数级的,没有语言限制。

对于大多数情况,将它们定义为指数是有意义的,因此它们彼此独立。在非常的情况下,您可以将指数标志值与预定义的状态值组合使用,这可能会受益:

public enum KitchenState{
    NothingHappening = 0,

    PanOnStove = 1,
    StoveOn = 2,
    Preheating = 3,

    EggsInPan = 4,
    EggsCooking = 7, 
}

在这种情况下,预热和EggsCooking是状态,PanOnStove,StoveOn和EggsInPan是标志。这主要是一种噱头,但它偶尔会派上用场