¿Cuál es la tilde (~) en la definición de enum?

Siempre me sorprende que incluso después de usar C # durante todo este tiempo, aún logré encontrar cosas que no sabía …

Intenté buscar en Internet esto, pero usar el “~” en una búsqueda no me funciona tan bien y tampoco encontré nada en MSDN (por no decir que no está allí)

Recientemente vi este fragmento de código, ¿qué significa la tilde (~)?

///  /// Enumerates the ways a customer may purchase goods. ///  [Flags] public enum PurchaseMethod { All = ~0, None = 0, Cash = 1, Check = 2, CreditCard = 4 } 

Me sorprendió un poco verlo, así que traté de comstackrlo, y funcionó … pero todavía no sé lo que significa / hace. ¿¿Alguna ayuda??

    ~ es el operador complementario de unario: voltea los bits de su operando.

     ~0 = 0xFFFFFFFF = -1 

    en aritmética de complemento a dos, ~x == -x-1

    el ~ operador se puede encontrar en prácticamente cualquier lenguaje que tome prestada la syntax de C, incluido Objective-C / C ++ / C # / Java / Javascript.

    Yo pensaría que:

     [Flags] public enum PurchaseMethod { None = 0, Cash = 1, Check = 2, CreditCard = 4, All = Cash | Check | CreditCard } 

    Sería un poco más claro.

     public enum PurchaseMethod { All = ~0, // all bits of All are 1. the ~ operator just inverts bits None = 0, Cash = 1, Check = 2, CreditCard = 4 } 

    Debido a dos complementos en C #, ~0 == -1 , el número donde todos los bits son 1 en la representación binaria.

    Es mejor que el

     All = Cash | Check | CreditCard 

    solución, porque si agrega otro método más tarde, diga:

     PayPal = 8 , 

    ya habrás terminado con la tilde-Todo, pero tendrás que cambiar la línea general por la otra. Por lo tanto, es menos propenso a errores más adelante.

    Saludos

    Solo una nota al margen, cuando uses

     All = Cash | Check | CreditCard 

    usted tiene el beneficio adicional de que Cash | Check | CreditCard Cash | Check | CreditCard Cash | Check | CreditCard evaluaría a All y no a otro valor (-1) que no es igual a todos mientras contiene todos los valores. Por ejemplo, si usa tres casillas de verificación en la interfaz de usuario

     [] Cash [] Check [] CreditCard 

    y sume sus valores, y el usuario los selecciona a todos, verá All en la enumeración resultante.

    Para otros que encontraron esta pregunta esclarecedora, tengo un rápido ~ ejemplo para compartir. El siguiente fragmento de la implementación de un método de pintura, como se detalla en esta documentación de Mono , usa ~ con gran efecto:

     PaintCells (clipBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.SelectionBackground); 

    Sin el operador ~ , el código probablemente se vería así:

     PaintCells (clipBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.Focus); 

    … porque la enumeración se ve así:

     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 } 

    ¿Nota la similitud de esta enum con la respuesta de Sean Bright?

    Creo que lo más importante para mí es que ~ es el mismo operador en una enumeración que en una línea normal de código.

    Es un operador de complemento. Aquí hay un artículo que a menudo me refiero para operadores de bit a bit

    http://www.blackwasp.co.uk/CSharpLogicalBitwiseOps.aspx

    También msdn lo usa en su artículo de enums que demuestra que usa mejor

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

    La alternativa que personalmente uso, que hace lo mismo que la respuesta de @Sean Bright pero me parece mejor, es esta:

     [Flags] public enum PurchaseMethod { None = 0, Cash = 1, Check = 2, CreditCard = 4, PayPal = 8, BitCoin = 16, All = Cash + Check + CreditCard + PayPal + BitCoin } 

    Observe cómo la naturaleza binaria de esos números, que son todos los poderes de dos, hace verdadera la siguiente aserción: (a + b + c) == (a | b | c) . Y en mi humilde opinión, + ve mejor.

    He hecho algunos experimentos con el ~ y me parece que podría haber peligros. Considere este fragmento de LINQPad que muestra que el valor de Todas las enumeraciones no se comporta como se espera cuando todos los valores se fusionan.

     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 } 

    Solo quiero agregar, si usa [Flags] enum, entonces puede ser más conveniente usar un operador de desplazamiento a la izquierda bit a bit, 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 }