new features c# bitwise-operators logical-operators

c# 7 new features



Diferencia entre ! y ~ en c# (3)

La primera vez que aprendí a escribir programas, usé C. (aplicaciones de línea de comandos muy básicas) En ambos idiomas, ¡usas el! - operador normalmente le gusta esto:

if(!true){ //false.. }

Quería hacer un poco de máscara de bits en c # y me preguntaba sobre el operador ''~''.

¡Ahora estoy un poco confundido porque en mi propia comprensión! y ~ debería hacer lo mismo.

Esto funciona en c #:

int i = ~0xffffffff; // i = 0 bool j = !true; // j = false

Esto no: (pero funciona en c y hace exactamente lo que esperaba)

int i = !0xffffffff; // i = 0

Entonces, ¿cuál es la diferencia entre ~ y! ¿Y por qué los separaron?


C # tomó la decisión de separar completamente las operaciones de enteros de las operaciones booleanas. Por ejemplo, no puede hacer if(x & 4) debe hacerlo if((x & 4) != 0) para moverse explícitamente de enteros a booleanos.

Esto está en línea con más de 4 décadas de experiencia con C y sus predecesores en los que las personas a menudo han cometido errores, como por ejemplo, dos valores que tenían un valor de true y se volvían false porque, aunque ambos eran distintos de cero, tenían No hay bits distintos de cero en común.

C y C ++ introdujeron un tipo bool final de su historia para agregar una diferencia más explícita entre enteros que representan números o patrones de bits, y valores en los que solo nos preocupamos por los valores de verdad, pero debíamos ser compatibles con el código más antiguo. C # tuvo el lujo de ser aún más explícito.

Con eso en mente, C # ''s ! y ~ son exactamente lo mismo que en C, excepto que algunas cosas ya no tienen sentido:

En c Niega el valor de verdad. Convierte 0 (falso) en 1 (verdadero) y todo lo que no es cero (verdadero) en 0 (falso). En C # eso solo tiene sentido con bool , no con int .

En C ~ produce el complemento de uno; Produce un valor donde cada 1 bit se convierte en 0 y cada 0 bit se convierte en 1 (por ejemplo, 0xFFFFFFFF se convierte en 0, 0xF0F0F0F0 se convierte en 0x0F0F0F0F y así sucesivamente). En C # eso tiene sentido con int , pero no con bool .

Si desea hacer el equivalente de !someInteger en C #, haga someInteger == 0 .

Editar:

Vale la pena señalar que a veces hay cierta confusión causada por la división de los operadores en "bitwise" (''&'', ''|'' y ''~'') y "boolean" (''&&'', ''||'' and ''!'') . Esta distinción no es del todo correcta.

Ahora, los últimos tres solo tienen sentido en contextos booleanos, y por lo tanto, dado que C # tiene una separación más estricta entre los valores booleanos y enteros, ya no se aplican a los enteros.

''~'' de hecho no tiene sentido en contextos booleanos (''~ x'' donde ''x'' es verdadero producirá una ''x'' que aún es cierta, 4294967294 veces de 4294967295), y así con C # ya no se aplica a bools .

''&'' y ''|'' retener un uso booleano sin embargo. En el caso de que ''A ()'' y ''B ()'' devuelvan un bool , entonces A() && B() solo llamarán B() si A() es falso (es decir, "cortocircuitos "), A() & B() siempre llamarán a ambos métodos, antes de hacer la Aritmética booleana. Esto tiende a ser raro porque:

  1. La mayoría de las veces, llamar a B() es solo una pérdida de tiempo, y el cortocircuito puede darnos un aumento de rendimiento que va desde masivo (si B() es caro) hasta hecho sin diferencia, pero no lo hicimos De todos modos, t-pierde-cualquier cosa, así que es un hábito. (Pero considere que si B() es muy barato, el costo de llamarlo podría ser más barato que el de la sucursal, especialmente si se predice mal, consulte los comentarios a continuación).

  2. A veces, && es obligatorio, como en x != null && x.Length != 0 donde no un cortocircuito arrojaría una excepción en el segundo argumento.

  3. Si es tan importante asegurarse de que se hayan llamado ambos métodos, entonces es mejor codificar para hacer esto en declaraciones separadas, para dejarlo claro a otros desarrolladores (o a usted mismo cuando regrese más tarde).

Pero si vamos a hablar sobre la diferencia entre operadores con argumentos booleanos y enteros, deberíamos incluir el uso booleano de | y & , porque aparecen (¡a veces a través de errores tipográficos!), y pueden causar confusión si las personas están separando falsamente "operadores de bit a bit" y "operadores booleanos" y olvidan que hay dos símbolos que se usan como ambos.



~ El operador NO bit a bit es un operador unario, ya que incluye un solo operando. A diferencia de los otros operadores bitwise, la versión bitwise no usa el mismo símbolo que el operador booleano similar. Para lograr el complemento de uno, el carácter de tilde (~) se coloca a la izquierda del valor a modificar.

byte valueToComplement = 187; // 10111011 byte complement = (byte) ~valueToComplement; // Result = 68

! - es un invertido booleano que puede ser verdadero o falso.