1

すべてのビット単位の例で、値が指数関数的にインクリメントされていることがわかります (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ます。

それは完璧に機能しているように見えますが、ビットごとにどこでも見られる値の指数関数的な増加はどうなっていますか?

4

3 に答える 3

3

問題なく動作しているようです

それはあなたが「完璧に」とは何を意味するかによります。

本当にBitWiseTest.OneOrBitwiseTest.Twoを等しくしたいですBitwiseTest.Threeか? それが現時点で得られるものであり、通常は理想的ではありません...通常、フラグを独立させたいと考えています。つまり、フラグはバイナリ表現で独立したビットで表す必要があります-そしてそれはまさにあなたが得たものです1、2、4、8、16 などの値を使用します。

于 2013-02-21T14:56:11.333 に答える
2

通常、列挙型には 2 種類あります。列挙型の場合:

  1. いずれかの値が使用されます。
  2. 値の組み合わせが使用されます。

値の 1 つが使用されます

この場合、好きな方法で列挙メンバーに番号を付けることができます。同じ意味であれば、同じ値を持つ 2 つのメンバーを持つこともできます。例えば:

Enum Comparison
    None = 0
    CaseSensitive = 1
    IgnoreCase = 2

    Default = 1
End Enum

値の組み合わせが使用されます

値はブール値になりました。オン(使用、指定) またはオフ(未使用、または指定) のいずれかです。これは、1 (オン) または 0 (オフ) のビットに適切に変換されます。値を互いに区別できるようにするには、2 の累乗を使用する必要があります。次に、特定のビットに対して、そのビットをオンまたはオフに設定できる値は 1 つだけです。

<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

2 つの値を組み合わせて新しい値を取得し、値を区別できるようになりました。

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

あなたの例について

あなたの例のバイナリ値を見てください。値OneTwoおよびFourは 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 TwoTrueいつvalueThreeSixまたはSevenであり、おそらく今あなたが望むものでもあります。その理由は、 に設定されている 1 ビットTwoが にも存在するためThreeSixありSeven、値の選択方法が原因です。

于 2013-02-21T19:16:08.013 に答える
0

それらは指数関数的である必要はありません、そのための言語制限はありません。

ほとんどの場合、それらを互いに独立するように指数関数的に定義することは理にかなっています。ごくまれに、指数フラグ値を事前定義された状態値と組み合わせることでメリットが得られる場合があります。

public enum KitchenState{
    NothingHappening = 0,

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

    EggsInPan = 4,
    EggsCooking = 7, 
}

この場合、予熱とEggsCookingは状態であり、PanOnStove、StoveOn、およびEggsInPanはフラグです。これは主にギミックですが、場合によっては便利です。

于 2013-02-21T15:20:32.140 に答える