18

¿Por qué el soporte bool? no se levantó && y ||? Podrían haber levantado los operadores true y false que indirectamente habrían agregado && y || levantados.¿Por qué no hay operadores de cortocircuito elevados en `bool?`?

Los operadores | y & ya están levantados e implementan el Three-valued logic correcto. Pero, por supuesto, no están en cortocircuito como || y &&.

La pregunta es por qué decidieron no levantar esos operadores al crear la especificación. Entonces, "es así porque la especificación lo dice", no hay respuesta al "¿por qué?".

Al levantar true y false de manera que no es ni nulltrue ni false:

public static bool operator true(bool? x) 
{ 
    return x.HasValue && x.Value 
} 

public static bool operator false(bool? x) 
{ 
    return x.HasValue && !x.Value 
} 

Esto habría dado lugar a && y || comportarse igual que sus contrapartes no-cortocircuito. Excepto que false && anything y true || anything serían cortocircuitos (false y true no hay constantes de tiempo de compilación en estos dos ejemplos).

Esto funcionaría muy similar al DBBool example on MSDN.

No veo ningún comportamiento sorprendente o peligroso al levantar estos operadores. ¿Me he perdido algo?

He leído another SO question sobre esto, pero no encontré ninguna de las respuestas satisfactoria.


respuesta de Jeff Yates muestra una buena razón de por qué el levantamiento de las true/false operadores no es óptima, no explica por qué levantar && y || directamente es malo. Como el levantamiento del operador es mágico para el compilador, en casos especiales Nullable<T> no es necesario seguir las reglas de sobrecarga para tipos normales y, por lo tanto, podría ofrecer &&/|| sin levantar true.

+3

¿No supondría esto que NULL significa falso? No todos estarían de acuerdo con eso. En, por ejemplo, La teoría relacional (y SQL) 'NULL AND true, NULL y NULL, FALSE O NULL' es .. NULL, que no es verdadera ni falsa – nos

+0

El operador' false' aplicado a 'null' devuelve false. Esto lleva a que '&&' no cortocircuite y devuelva 'null y cualquier cosa' en su lugar. – CodesInChaos

+0

http://en.wikipedia.org/wiki/Three-valued_logic – Jan

Respuesta

0

false && anything es lo mismo que false. Sin embargo, si espera que false && anything sea verdadero solo si anything es falso, entonces !anything es lo que desea.

También, true || anything es el mismo que true. ... Y no estoy seguro de cómo podría hacer que devuelva falso en cualquier condición, ya que no tendría sentido que "esto o aquello" no devuelva nada.

... ¿por qué agregar peso adicional a la condición cuando todo es claro y simple como es?

No suelo ser un adepto de "porque esto es así", pero no veo la ventaja de agregar dicha funcionalidad.

+0

No me refiero a 'false' como una constante en tiempo de compilación en ese ejemplo. Pero una expresión que ya se ha evaluado como falsa, y por lo tanto hace innecesaria la evaluación del lado derecho. – CodesInChaos

+0

falso && todo es falso. ¿no? – Andrey

+1

¡oh! entonces, ¿estás hablando de 'cond1 && cond2' mientras quieres que' cond2' sea evaluado incluso si 'cond1' es falso? –

4

Lo que usted propone crearía dos patrones de uso diferentes para tipos anulables.

Considere el siguiente código:

bool? a = null; 

// This doesn't currently compile but would with lifted true/false operators. 
if (a) 
{ 
} 

// Whereas this provides a consistent use of nullable types. 
if (a ?? false) 
{ 
} 

Para mantener la coherencia en el uso de tipos anulables, tiene sentido a no levantar las true y false operadores en bool. No sé si esta es la verdadera razón por la que no se hizo, pero tiene sentido para mí.

+0

No sabía que 'if' usa el operador' true'. Pensé que requiere una conversión implícita a 'bool'. Pero acabo de probarlo y tienes razón. Aún así, esto no explica por qué no levantaron && y || directamente sin levantar 'true' o' false'. – CodesInChaos

+1

@CodeInChaos: ¿Cómo pudiste? && y || requiere booleanos en cualquier lado (ver especificación) - sin levantar 'true' o' false', no se puede hacer. –

4

Ya que mostraron que el levantamiento true y false es técnicamente posible, sólo hay dos posibles respuestas a su pregunta (con "ellos" siendo la gente que escribió el compilador/spec):

  1. Es un error en la especificación, es decir. ellos no pensaron en esto. (posible, pero lo dudo)
  2. Pensaron que el levantamiento de los operadores de cortocircuito es potencialmente propenso a errores. Podría ser la misma forma de razonar que por qué C# está completamente basado en clases (no tiene funciones exclusivas como en C++) o por qué una sentencia como if (myNullVar) { ... } (con myNullVar siendo una referencia) no funciona en C# (pero sí en C/C++)

Creo que siempre hay un equilibrio entre hacer que un lenguaje de programación sea más potente y hacerlo menos propenso a errores.

Actualización: sólo por su interés, que es lo que el official documentation dice:

Esto no está permitido porque no está claro lo que significa nula en el contexto de un condicional.

+2

Esta respuesta muestra muy bien por qué levantar 'op_true' /' op_false' es una mala idea dada la forma en que se implementan los condicionales (IMO usando 'op_true' en condicionales es estúpido, requeriría convertibilidad implícita a bool) no muestra por qué los operadores en cortocircuito no deberían levantarse directamente. – CodesInChaos

+1

@CodesInChaos: Cuando C# tomó la desafortunada decisión (en mi humilde opinión) de izar implícitamente todos los operadores en tipos anulables utilizando la formulación de que el resultado debería ser 'nulo' si cualquiera de los operandos era' nulo', eso significaba que 'verdadero | null' y 'false & null' no pueden evaluarse como' true' y 'false', respectivamente, como sería el caso con la lógica de tres valores, sino que deben evaluar' null' para mantener la coherencia con otros operadores izados. El significado normal de '&&' y '||' es que deben devolver el mismo valor que '&' y '|' si se les dan los mismos operandos, pero solo evalúan el operando correcto ... – supercat

+1

... cuando el valor podría afectar el resultado. Si bien sería posible tener '&&' y '||' de tal manera que sean consistentes con '&' y '|' evaluando el lado derecho cuando el operando de la izquierda no sea nulo, lo haría sería bastante sorprendente si, dado 'bool b = falso; bool? bq = false; ', la expresión' bq && f() 'evaluó el lado derecho aunque' b & f() 'no. – supercat

Cuestiones relacionadas