/ / Operacje bitowe - sprawdzanie i usuwanie - vb.net, operatory bitowe, bitowe i bitowe-xor

Operacje bitowe - sprawdzanie i usuwanie - vb.net, operatory bitowe, bitowe i bitowe-xor

Zwróć uwagę na prosty przykład poniżej:

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

Pierwsza część mojego pytania dotyczy linii If (test And Names.Test3) = Names.Test3.

Czy nie byłoby lepiej po prostu sprawdzić If test And Names.Test3 tak jakby flaga była dostępna? Jeśli wartość jest niezerowa (co oznacza, że ​​flaga istnieje), to wynikiem będzie warunek True tak czy inaczej.

Czy istnieje dobry powód, aby użyć pierwszego sposobusprawdzanie drugiego? (Podczas gdy moja odpowiedź dotyczy VB.NET, byłbym również zainteresowany wiedząc, czy jest to potencjalna pułapka gdziekolwiek indziej, tj. C #, C ++ itd.).

Co się tyczy usuwania flag, wydaje się, że można to zrobić na dwa sposoby:

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

Jednak pierwszy doda flagę, jeśli jestbrakuje i usuń go, jeśli jest, podczas gdy drugi go tylko usunie. Czy to jedyna różnica? Czy istnieje inny powód, dla którego powinienem preferować jedną metodę nad drugą?

Odpowiedzi:

3 dla odpowiedzi № 1

Masz rację stwierdzając, że możesz skutecznie zastąpić to:

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

z tym

If (test And Names.Test3) Then

Ale, drugi przykład nie będzie się kompilował z Option Strict On jak słusznie dostałeś błąd:

Option Strict On disallows implicit conversions from "Names" to "Boolean" więc aby to skompilować, musisz owinąć a CBool zaokrąglij to.

Podsumowując, powiedziałbym, że o wiele lepiej jest użyć pierwszego przykładu, ponieważ zamiar jest bardzo jasny: - sprawdzasz, czy ustawiony jest bit.

Jeśli chodzi o usuwanie flag, tj. Rozbrajanie bitów, powinieneś użyć:

test = test And Not Names.Test3

Za pomocą Xor daje efekt przełączanie wartość.

Poniższe mogą pomóc (zwłaszcza jeśli uczynisz je metodami rozszerzenia):

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

2 dla odpowiedzi nr 2

Zapamietaj to Flags nie wszystkie muszą być wartościami czysto jednobitowymi. Wyobraź sobie (z lepszymi nazwami), że Twoje wyliczenie było:

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

Teraz nie chciałbyś tego po prostu przetestować test And Names.Test2AndTest4 jest niezerowa, ponieważ nie odpowiada na prawidłowe pytanie, więc lepszym nawykiem jest zazwyczaj And twoją maskę, aby sprawdzić, a następnie porównać do wartości maski, aby to zapewnić wszystko ustawione są bity maski.