Mała uwaga: bitowe wyliczenie w języku C # powinno otrzymać nad nim atrybut [Flagi].
Nyerguds
@Nyerguds, czy możesz wyjaśnić, dlaczego powinien otrzymać atrybut?
etan
Daje lepszą obsługę IntelliSense podczas debugowania, ponieważ rozpoznaje nieznane wartości wyliczeniowe jako kombinacje istniejących wartości.
Nyerguds,
1
Zapewnia również bardziej znaczącą .ToString()wartość. np. RED, BLUE, YELLOWzamiast 22.
Sinjai
Odpowiedzi:
331
Musisz to &zrobić za pomocą ~(uzupełnienia) „NIEBIESKIEGO”.
Operator dopełniania zasadniczo odwraca lub „odwraca” wszystkie bity dla danego typu danych. Jako taki, jeśli użyjesz ANDoperatora ( &) z pewną wartością (nazwijmy tę wartość „X”) i dopełnieniem jednego lub więcej zestawów bitów (nazwijmy te bity Qi ich uzupełnienie ~Q), instrukcja X & ~Qusuwa wszelkie bity, które zostały ustawione w Qod Xi zwraca wynik.
Aby usunąć lub wyczyścić BLUEbity, użyj następującego oświadczenia:
colorsWithoutBlue = colors &~Blah.BLUE
colors &=~Blah.BLUE // This one removes the bit from 'colors' itself
Możesz również określić wiele bitów do wyczyszczenia, w następujący sposób:
colorsWithoutBlueOrRed = colors &~(Blah.BLUE |Blah.RED)
colors &=~(Blah.BLUE |Blah.RED)// This one removes both bits from 'colors' itself
lub na przemian ...
colorsWithoutBlueOrRed = colors &~Blah.BLUE &~Blah.RED
colors &=~Blah.BLUE &~Blah.RED // This one removes both bits from 'colors' itself
Pomyślałem, że może to być przydatne dla innych osób, które potknęły się tutaj, jak ja.
Uważaj, jak radzisz sobie z wartościami wyliczania, które możesz ustawić na wartość == 0 (czasami pomocne może być posiadanie stanu nieznanego lub bezczynności dla wyliczenia). Powoduje to problemy przy korzystaniu z tych operacji manipulacji bitami.
Również gdy masz wartości wyliczane, które są kombinacjami innej potęgi 2 wartości, np
publicenumColour{None=0,// default value
RED =2,
BLUE =4,
GREEN =8,
YELLOW =16,Orange=18// Combined value of RED and YELLOW}
W takich przypadkach przydatna może być taka metoda rozszerzenia:
publicstaticColourUnSet(thisColour states,Colour state){if((int)states ==0)return states;if(states == state)returnColour.None;return states &~state;}
A także ekwiwalentna metoda IsSet, która obsługuje połączone wartości (choć w nieco pospieszny sposób)
publicstaticboolIsSet(thisColour states,Colour state){// By default if not OR'dif(states == state)returntrue;// Combined: One or more bits need to be setif( state ==Colour.Orange)return0!=(int)(states & state);// Non-combined: all bits need to be setreturn(states & state)== state;}
Wydaje mi się, że prostszym rozwiązaniem jest uniknięcie użycia 0 jako flagi. I zazwyczaj ustawić flagi stałe teksty jak ten . Nie rozumiem, w jaki sposób możesz czerpać korzyści z określania stanu o wartości 0. W końcu chodzi o to, że możesz zająć się nazwami przyjaznymi dla programisty ( Red, Blue, Green), a nie wartościami podstawowymi, tak?
Sinjai
Posiadanie wpisu nonelub unknownlub unseto wartości == 0 jest w wielu przypadkach dobrą rzeczą, ponieważ nie zawsze można założyć, że określona wartość jest ustawieniem domyślnym, np. Jeśli masz tylko czerwony, niebieski i zielony, czy masz czerwony jako wartość domyślna (np. wartość, która ma wyliczenie, gdy jest tworzony lub użytkownik go nie zmodyfikował?)
Sverrir Sigmundarson
Czy nie możesz po prostu 1, 2, 4, 8ustawić Unset = 1 i używać jako wartości? Jeśli potrzebujesz wartości domyślnej, po to są domyślne konstruktory, prawda? Chciałbym zachować wszystko tak wyraźnie, jak to możliwe, ze względu na czytelność, a poleganie na wyliczeniu domyślnym na default(int)( 0), gdy nie podano wartości, mimo że informacje są prawdopodobnie znane przez dowolnego programistę, jest i tak zbyt sprytne jak na mój gust. Edycja: Och, czekaj, czy ustawienie Unset = 0 uniemożliwi istnienie czegoś Unset | Blue?
Sinjai
Jesteś na dobrej drodze w swojej edycji Sinjai, utrzymywanie wartości nieustalonej == 0 faktycznie rozwiązuje kilka problemów. Jednym z nich jest to, o czym wspomniałeś, a drugim jest to, że jeśli rozbroisz wszystkie wartości wyliczenia, wtedy nie potrzebujesz specjalnego przypadku dla „Unset”, jeśli jest ustawiony na zero. (np. jeśli Red & ~Redskończysz na zero, będziesz musiał mieć kod, aby sprawdzić tę sprawę i wyraźnie przypisać Unsetwartość)
Sverrir Sigmundarson
Gotcha Czy często masz do czynienia z nieuzbrojonymi flagami?
Sinjai,
2
Co z XOR (^)?
Biorąc pod uwagę, że flaga FLAG, którą próbujesz usunąć, już tam jest, będzie działać .. jeśli nie, będziesz musiał użyć &.
publicenumColour{None=0,// default value
RED =2,
BLUE =4,
GREEN =8,
YELLOW =16,Orange=18// Combined value of RED and YELLOW}
colors =(colors ^Colour.RED)& colors;
Aby uprościć wyliczanie flagi i sprawić, że lepiej będzie czytać unikając wielokrotności, możemy użyć przesunięcia bitów. (Z dobrego artykułu Kończenie wielkiej debaty na temat flag Enum )
[FLAG]EnumBlah{
RED =1,
BLUE =1<<1,
GREEN =1<<2,
YELLOW =1<<3}
.ToString()
wartość. np.RED, BLUE, YELLOW
zamiast22
.Odpowiedzi:
Musisz to
&
zrobić za pomocą~
(uzupełnienia) „NIEBIESKIEGO”.Operator dopełniania zasadniczo odwraca lub „odwraca” wszystkie bity dla danego typu danych. Jako taki, jeśli użyjesz
AND
operatora (&
) z pewną wartością (nazwijmy tę wartość „X”) i dopełnieniem jednego lub więcej zestawów bitów (nazwijmy te bityQ
i ich uzupełnienie~Q
), instrukcjaX & ~Q
usuwa wszelkie bity, które zostały ustawione wQ
odX
i zwraca wynik.Aby usunąć lub wyczyścić
BLUE
bity, użyj następującego oświadczenia:Możesz również określić wiele bitów do wyczyszczenia, w następujący sposób:
lub na przemian ...
Podsumowując:
X | Q
ustawia bityQ
X & ~Q
usuwa bityQ
~X
odwraca / odwraca wszystkie bityX
źródło
colors &= ~( Blah.BLUE | Blah.GREEN );
Inne odpowiedzi są poprawne, ale aby konkretnie usunąć niebieski z powyższego, napiszesz:
źródło
And not
to...............................źródło
Pomyślałem, że może to być przydatne dla innych osób, które potknęły się tutaj, jak ja.
Uważaj, jak radzisz sobie z wartościami wyliczania, które możesz ustawić na wartość == 0 (czasami pomocne może być posiadanie stanu nieznanego lub bezczynności dla wyliczenia). Powoduje to problemy przy korzystaniu z tych operacji manipulacji bitami.
Również gdy masz wartości wyliczane, które są kombinacjami innej potęgi 2 wartości, np
W takich przypadkach przydatna może być taka metoda rozszerzenia:
A także ekwiwalentna metoda IsSet, która obsługuje połączone wartości (choć w nieco pospieszny sposób)
źródło
Red, Blue, Green
), a nie wartościami podstawowymi, tak?none
lubunknown
lubunset
o wartości == 0 jest w wielu przypadkach dobrą rzeczą, ponieważ nie zawsze można założyć, że określona wartość jest ustawieniem domyślnym, np. Jeśli masz tylko czerwony, niebieski i zielony, czy masz czerwony jako wartość domyślna (np. wartość, która ma wyliczenie, gdy jest tworzony lub użytkownik go nie zmodyfikował?)1, 2, 4, 8
ustawić Unset = 1 i używać jako wartości? Jeśli potrzebujesz wartości domyślnej, po to są domyślne konstruktory, prawda? Chciałbym zachować wszystko tak wyraźnie, jak to możliwe, ze względu na czytelność, a poleganie na wyliczeniu domyślnym nadefault(int)
(0
), gdy nie podano wartości, mimo że informacje są prawdopodobnie znane przez dowolnego programistę, jest i tak zbyt sprytne jak na mój gust. Edycja: Och, czekaj, czy ustawienie Unset = 0 uniemożliwi istnienie czegośUnset | Blue
?Red & ~Red
skończysz na zero, będziesz musiał mieć kod, aby sprawdzić tę sprawę i wyraźnie przypisaćUnset
wartość)Co z XOR (^)?
Biorąc pod uwagę, że flaga FLAG, którą próbujesz usunąć, już tam jest, będzie działać .. jeśli nie, będziesz musiał użyć &.
źródło
Aby uprościć wyliczanie flagi i sprawić, że lepiej będzie czytać unikając wielokrotności, możemy użyć przesunięcia bitów. (Z dobrego artykułu Kończenie wielkiej debaty na temat flag Enum )
a także wyczyścić wszystkie bity
źródło
Możesz użyć tego:
źródło