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 ??

Foi útil?

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

http://msdn.microsoft.com/en-us/library/ cc138362.aspx

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
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top