Qual é o til (~) na definição enum?
-
23-08-2019 - |
Pergunta
Eu estou sempre surpreso que mesmo depois de usar C # para todo esse tempo agora, eu ainda conseguem encontrar coisas que eu não sabia sobre ...
Eu tentei pesquisar na internet para isso, mas usando o "~" em uma pesquisa não está funcionando para mim tão bem e eu não encontrar nada no MSDN ou (não quer dizer que não está lá)
Eu vi esse trecho de código recentemente, o que faz o til (~) média?
/// <summary>
/// Enumerates the ways a customer may purchase goods.
/// </summary>
[Flags]
public enum PurchaseMethod
{
All = ~0,
None = 0,
Cash = 1,
Check = 2,
CreditCard = 4
}
Eu estava um pouco surpreso ao vê-lo assim que eu tentei para compilá-lo, e ele funcionou ... mas eu ainda não sei o que isso significa / faz. Qualquer ajuda ??
Solução
~ é a de um unário operador complemento -. Ele inverte os bits de seu operando
~0 = 0xFFFFFFFF = -1
em dois complemento da aritmética, ~x == -x-1
o operador ~ podem ser encontrados em praticamente qualquer idioma que emprestado sintaxe do C, incluindo Objective-C / C ++ / C # / Java / Javascript.
Outras dicas
Eu acho que:
[Flags]
public enum PurchaseMethod
{
None = 0,
Cash = 1,
Check = 2,
CreditCard = 4,
All = Cash | Check | CreditCard
}
Seria um pouco mais clara.
public enum PurchaseMethod
{
All = ~0, // all bits of All are 1. the ~ operator just inverts bits
None = 0,
Cash = 1,
Check = 2,
CreditCard = 4
}
Por causa de dois complemento em C #, ~0 == -1
, o número onde todos os bits são 1 na representação binária.
É melhor do que o
All = Cash | Check | CreditCard
solução, porque se você adicionar um outro método depois, dizer:
PayPal = 8 ,
você vai ser feito com o til-All, mas tem que mudar a linha de todos com o outro. Portanto, a sua menos depois sujeito a erros.
relação
Apenas uma nota lateral, quando você usa
All = Cash | Check | CreditCard
você tem a vantagem adicional de que Cash | Check | CreditCard
iria avaliar a All
e não para outro valor (-1) que não é igual para todos, enquanto que contém todos os valores.
Por exemplo, se você usar três caixas de seleção na interface do usuário
[] Cash
[] Check
[] CreditCard
e soma os seus valores, e o usuário selecionar todos eles, você veria All
na enumeração resultante.
Para outros que encontraram esta pergunta esclarecedora, eu tenho um exemplo ~
rápido a ação. O seguinte trecho da implementação de um método de pintura, conforme detalhado na esta documentação Mono , usos ~
com grande efeito:
PaintCells (clipBounds,
DataGridViewPaintParts.All & ~DataGridViewPaintParts.SelectionBackground);
Sem o operador ~
, o código seria provavelmente algo parecido com isto:
PaintCells (clipBounds, DataGridViewPaintParts.Background
| DataGridViewPaintParts.Border
| DataGridViewPaintParts.ContentBackground
| DataGridViewPaintParts.ContentForeground
| DataGridViewPaintParts.ErrorIcon
| DataGridViewPaintParts.Focus);
... porque os olhares de enumeração como este:
public enum DataGridViewPaintParts
{
None = 0,
Background = 1,
Border = 2,
ContentBackground = 4,
ContentForeground = 8,
ErrorIcon = 16,
Focus = 32,
SelectionBackground = 64,
All = 127 // which is equal to Background | Border | ... | Focus
}
semelhança Aviso deste enum a resposta de Sean Bright?
Eu acho que o take mais importante embora para mim é que ~
é o mesmo operador em uma enumeração, uma vez que está em uma linha normal de código.
É um operador de complemento, Aqui está um artigo que eu muitas vezes referem-se para os operadores bit a bit
http://www.blackwasp.co.uk/CSharpLogicalBitwiseOps.aspx
também usa MSDN-lo em seu artigo enums que demonstra que usar melhor
A I alternativa pessoalmente uso, que faz a mesma coisa do que a resposta de @Sean brilhante, mas parece melhor para mim, é esta:
[Flags]
public enum PurchaseMethod
{
None = 0,
Cash = 1,
Check = 2,
CreditCard = 4,
PayPal = 8,
BitCoin = 16,
All = Cash + Check + CreditCard + PayPal + BitCoin
}
Observe como a natureza binária desses números, que são todas as potências de dois, faz a seguinte afirmação verdadeira: (a + b + c) == (a | b | c)
. E IMHO, olhares +
melhores.
Eu tenho feito algumas experiências com o ~ e encontrá-lo que ele poderia ter armadilhas. Considere este trecho para LINQPad que mostra que o valor de enumeração Todos não se comporta como esperado quando todos os valores são ored juntos.
void Main()
{
StatusFilterEnum x = StatusFilterEnum.Standard | StatusFilterEnum.Saved;
bool isAll = (x & StatusFilterEnum.All) == StatusFilterEnum.All;
//isAll is false but the naive user would expect true
isAll.Dump();
}
[Flags]
public enum StatusFilterEnum {
Standard =0,
Saved =1,
All = ~0
}
Só quero acrescentar, se você usar [Flags] enum, então ele pode ser mais conveniente usar bit a bit operador de deslocamento para a esquerda, como este:
[Flags]
enum SampleEnum
{
None = 0, // 0
First = 1 << 0, // 1b = 1d
Second = 1 << 1, // 10b = 2d
Third = 1 << 2, // 100b = 4d
Fourth = 1 << 3, // 1000b = 8d
All = ~0 // 11111111b
}