Nota pequena: uma enumeração bit a bit em C # deve obter o atributo [Flags] acima dele.
Nyerguds
@ Nyerguds, você poderia explicar por que deveria obter o atributo?
19717
Ele oferece um suporte melhor ao IntelliSense durante a depuração, porque reconhece valores de enumeração desconhecidos como combinações de valores existentes.
Nyerguds
1
Ele também fornece um .ToString()valor mais significativo . por exemplo, em RED, BLUE, YELLOWvez de 22.
Sinjai
Respostas:
331
Você precisa fazer &isso com o ~(complemento) de 'AZUL'.
O operador complemento essencialmente reverte ou 'vira' todos os bits para o tipo de dados fornecido. Assim, se você usar o ANDoperador ( &) com algum valor (vamos chamar esse valor de 'X') e o complemento de um ou mais bits definidos (vamos chamar esses bits Qe seu complemento ~Q), a instruçãoX & ~Q limpará todos os bits que foram configurados em Qfrom Xe retorna o resultado.
Portanto, para remover ou limpar os BLUEbits, use a seguinte instrução:
colorsWithoutBlue = colors &~Blah.BLUE
colors &=~Blah.BLUE // This one removes the bit from 'colors' itself
Você também pode especificar vários bits para limpar, da seguinte maneira:
colorsWithoutBlueOrRed = colors &~(Blah.BLUE |Blah.RED)
colors &=~(Blah.BLUE |Blah.RED)// This one removes both bits from 'colors' itself
ou alternadamente ...
colorsWithoutBlueOrRed = colors &~Blah.BLUE &~Blah.RED
colors &=~Blah.BLUE &~Blah.RED // This one removes both bits from 'colors' itself
então, se eu quisesse remover mais, faria: & = ~ Blah.BLUE & ~ Blah.Green?
Blankman
11
Melhor écolors &= ~( Blah.BLUE | Blah.GREEN );
par
2
que incomum, eu estava pensando em como fazer isso mais uma vez cerca de 5 dias atrás :) Esta pergunta foi atualizada na minha caixa de entrada e pronto!
quer
Ótima resposta. Eu acho que você quer dizer "& =" não "= &" em seus exemplos de código no entanto;)
Dave Jellison
48
As outras respostas estão corretas, mas para remover especificamente o azul das opções acima, você deve escrever:
Achei que isso poderia ser útil para outras pessoas que tropeçaram aqui como eu.
Tenha cuidado ao lidar com quaisquer valores de enumeração que você pode definir para ter um valor == 0 (às vezes pode ser útil ter um estado Desconhecido ou Inativo para uma enumeração). Causa problemas ao confiar nessas operações de manipulação de bits.
Além disso, quando você tem valores de enumeração que são combinações de outra potência de 2 valores, por exemplo,
publicenumColour{None=0,// default value
RED =2,
BLUE =4,
GREEN =8,
YELLOW =16,Orange=18// Combined value of RED and YELLOW}
Nesses casos, um método de extensão como esse pode ser útil:
publicstaticColourUnSet(thisColour states,Colour state){if((int)states ==0)return states;if(states == state)returnColour.None;return states &~state;}
E também o método IsSet equivalente que lida com os valores combinados (embora de um jeito meio hacky)
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;}
Parece-me que a solução mais simples é evitar o uso de 0 como sinalizador. Eu normalmente configuro enums de flag como este . Não vejo como você se beneficia ao especificar um estado com um valor 0. Afinal, o ponto principal é que você pode se preocupar com os nomes amigáveis ao programador ( Red, Blue, Green) e não com os valores subjacentes, sim?
Sinjai
Ter uma entrada noneou unknownou unsetcom valor == 0 é, em muitos casos, uma coisa boa, pois nem sempre é possível assumir que um valor específico é o conjunto padrão; por exemplo, se você tiver apenas vermelho, azul e verde, terá vermelho como o valor padrão (por exemplo, o valor que o enum tem quando é criado ou o usuário não tenha modificado?)
Sverrir Sigmundarson
Você não pode simplesmente ter Unset = 1 e usar 1, 2, 4, 8como seus valores? Se você precisa de um valor padrão, é para isso que servem os construtores padrão, certo? Eu gosto de manter as coisas o mais explícitas possível, por questões de legibilidade, e confiar em um enum para usar como padrão default(int)( 0) quando não receber um valor, apesar de serem informações presumivelmente conhecidas por qualquer desenvolvedor, é muito sorrateiro para o meu gosto. Edit: Oh espere, fazer Unset = 0 impedir que algo seja Unset | Blue?
Sinjai
Você está no caminho certo em sua edição Sinjai, mantendo o valor não definido == 0 na verdade resolve alguns problemas. Um sendo o que você mencionou e outro sendo, se você desarmar todos os valores de enumeração, não precisará de um caso especial para "Desativar" se estiver definido como zero. (por exemplo, se você Red & ~Red, em seguida, você acabar com zero, você então tem que ter código para verificar para este caso e atribuir explicitamente o Unsetvalor)
Sverrir Sigmundarson
Peguei vocês. Você costuma lidar com bandeiras não definidas?
Sinjai 02/0318
2
E o xor (^)?
Dado que o FLAG que você está tentando remover está lá, ele funcionará. Caso contrário, você precisará usar um &.
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;
.ToString()
valor mais significativo . por exemplo, emRED, BLUE, YELLOW
vez de22
.Respostas:
Você precisa fazer
&
isso com o~
(complemento) de 'AZUL'.O operador complemento essencialmente reverte ou 'vira' todos os bits para o tipo de dados fornecido. Assim, se você usar o
AND
operador (&
) com algum valor (vamos chamar esse valor de 'X') e o complemento de um ou mais bits definidos (vamos chamar esses bitsQ
e seu complemento~Q
), a instruçãoX & ~Q
limpará todos os bits que foram configurados emQ
fromX
e retorna o resultado.Portanto, para remover ou limpar os
BLUE
bits, use a seguinte instrução:Você também pode especificar vários bits para limpar, da seguinte maneira:
ou alternadamente ...
Então, para resumir:
X | Q
define bit (s)Q
X & ~Q
limpa bit (s)Q
~X
vira / inverte todos os bitsX
fonte
colors &= ~( Blah.BLUE | Blah.GREEN );
As outras respostas estão corretas, mas para remover especificamente o azul das opções acima, você deve escrever:
fonte
And not
isto...............................fonte
Achei que isso poderia ser útil para outras pessoas que tropeçaram aqui como eu.
Tenha cuidado ao lidar com quaisquer valores de enumeração que você pode definir para ter um valor == 0 (às vezes pode ser útil ter um estado Desconhecido ou Inativo para uma enumeração). Causa problemas ao confiar nessas operações de manipulação de bits.
Além disso, quando você tem valores de enumeração que são combinações de outra potência de 2 valores, por exemplo,
Nesses casos, um método de extensão como esse pode ser útil:
E também o método IsSet equivalente que lida com os valores combinados (embora de um jeito meio hacky)
fonte
Red, Blue, Green
) e não com os valores subjacentes, sim?none
ouunknown
ouunset
com valor == 0 é, em muitos casos, uma coisa boa, pois nem sempre é possível assumir que um valor específico é o conjunto padrão; por exemplo, se você tiver apenas vermelho, azul e verde, terá vermelho como o valor padrão (por exemplo, o valor que o enum tem quando é criado ou o usuário não tenha modificado?)1, 2, 4, 8
como seus valores? Se você precisa de um valor padrão, é para isso que servem os construtores padrão, certo? Eu gosto de manter as coisas o mais explícitas possível, por questões de legibilidade, e confiar em um enum para usar como padrãodefault(int)
(0
) quando não receber um valor, apesar de serem informações presumivelmente conhecidas por qualquer desenvolvedor, é muito sorrateiro para o meu gosto. Edit: Oh espere, fazer Unset = 0 impedir que algo sejaUnset | Blue
?Red & ~Red
, em seguida, você acabar com zero, você então tem que ter código para verificar para este caso e atribuir explicitamente oUnset
valor)E o xor (^)?
Dado que o FLAG que você está tentando remover está lá, ele funcionará. Caso contrário, você precisará usar um &.
fonte
Para simplificar a enumeração do sinalizador e facilitar a leitura, evitando múltiplos, podemos usar a mudança de bits. (De um bom artigo Terminando o Grande Debate sobre Bandeiras Enum )
e também para limpar todos os bits
fonte
Você pode usar isto:
fonte