Wiele razy widzę deklaracje wyliczeń flag, które używają wartości szesnastkowych. Na przykład:
[Flags]
public enum MyEnum
{
None = 0x0,
Flag1 = 0x1,
Flag2 = 0x2,
Flag3 = 0x4,
Flag4 = 0x8,
Flag5 = 0x10
}
Kiedy deklaruję wyliczenie, zwykle deklaruję to w ten sposób:
[Flags]
public enum MyEnum
{
None = 0,
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 8,
Flag5 = 16
}
Czy istnieje powód lub uzasadnienie, dlaczego niektórzy ludzie wybierają zapisywanie wartości w systemie szesnastkowym, a nie dziesiętnym? Z mojego punktu widzenia łatwiej się pomylić, używając wartości szesnastkowych i przypadkowo Flag5 = 0x16
zamiast pisać Flag5 = 0x10
.
c#
.net
enums
enum-flags
Adi Lester
źródło
źródło
10
zamiast0x10
używać liczb dziesiętnych? Zwłaszcza, że mamy do czynienia z liczbami binarnymi, a hex jest trywialnie zamienialne na / z binarnego?0x111
jest o wiele mniej denerwujące w tłumaczeniu w głowie niż273
...Flag1 | Flag2
to 3, a 3 nie odpowiada żadnej wartości domenyMyEnum
.Odpowiedzi:
Racjonalne uzasadnienia mogą się różnić, ale widzę zaletę, że szesnastkowy przypomina: „OK, nie mamy już do czynienia z liczbami w arbitralnym, wymyślonym przez ludzi świecie o podstawie dziesiątki. Mamy do czynienia z bitami - światem maszyny - i będziemy grać według jego zasad ”. Szesnastkowy jest rzadko używany, chyba że masz do czynienia z tematami stosunkowo niskiego poziomu, w których liczy się układ pamięci. Używanie go wskazuje na fakt, że w takiej sytuacji jesteśmy teraz.
Ponadto nie jestem pewien co do języka C #, ale wiem, że w języku C
x << y
jest to poprawna stała czasu kompilacji. Korzystanie z przesunięć bitowych wydaje się najbardziej jasne:źródło
x << y
notacją.1 << 10 = KB
,1 << 20 = MB
,1 << 30 = GB
I tak dalej. To naprawdę fajne, jeśli chcesz zrobić 16-kilobajtową tablicę dla bufora, który możesz po prostu iśćvar buffer = new byte[16 << 10];
Dzięki temu łatwo zauważyć, że są to flagi binarne .
Chociaż postęp czyni to jeszcze wyraźniejszym:
źródło
012
jest w rzeczywistości10
.int
zamiast tego czułbym się bezpiecznie . Wiem, że to głupie ... ale nawyki ciężko umierają.Myślę, że dzieje się tak dlatego, że sekwencja zawsze wynosi 1, 2, 4, 8, a następnie dodaj 0.
Jak widać:
i tak dalej, o ile pamiętasz sekwencję 1-2-4-8, możesz zbudować wszystkie kolejne flagi bez konieczności pamiętania o potęgach 2
źródło
Ponieważ
[Flags]
oznacza, że wyliczenie to naprawdę pole bitowe . Ze[Flags]
można użyć bitowego AND (&
) i OR (|
) Operatorzy połączyć flagi. W przypadku takich wartości binarnych prawie zawsze bardziej oczywiste jest użycie wartości szesnastkowych. To jest właśnie powód, dla którego używamy szesnastkowego w pierwszej kolejności. Każdy znak szesnastkowy odpowiada dokładnie jednemu półbajtowi (cztery bity). W przypadku liczb dziesiętnych to mapowanie od 1 do 4 nie jest prawdziwe.źródło
Ponieważ istnieje mechaniczny, prosty sposób na podwojenie potęgi dwóch w hex. W liczbach dziesiętnych jest to trudne. Wymaga długiego mnożenia w twojej głowie. W hex to prosta zmiana. Możesz to zrobić aż do momentu, w
1UL << 63
którym nie możesz tego zrobić w systemie dziesiętnym.źródło
Ponieważ łatwiej jest śledzić ludziom, gdzie bity są we fladze. Każda cyfra szesnastkowa może pasować do 4-bitowej liczby dwójkowej.
Zazwyczaj chcesz, aby twoje flagi nie nakładały się na bity, najłatwiejszym sposobem zrobienia tego i wizualizacji jest użycie wartości szesnastkowych do deklarowania flag.
Tak więc, jeśli potrzebujesz flag z 16 bitami, użyjesz 4-cyfrowych wartości szesnastkowych i w ten sposób unikniesz błędnych wartości:
źródło