2010-07-07 24 views
20

¿Cuál es la razón por la cual null no se evalúa como false en condicionales?¿Por qué no se evalúa nulo en falso?

Primero pensé en las asignaciones para evitar el error de usar = en lugar de ==, pero esto podría ser fácilmente rechazado por el compilador.

if (someClass = someValue) // cannot convert someClass to bool. Ok, nice 

if (someClass) // Cannot convert someClass to bool. Why? 

if (someClass != null) // More readable? 

creo que es bastante razonable suponer que null significa false. Hay otros idiomas que usan esto también, y no he tenido un error debido a eso.

Edit: Y, por supuesto, me refiero a los tipos de referencia.

Un buen comentario de Daniel Earwicker en el error de asignación ... Esto compila sin una advertencia, ya que se evalúa como bool:

bool bool1 = false, bool2 = true; 
if (bool1 = bool2) 
{ 
    // oops... false == true, and bool1 became true... 
} 
+0

La respuesta simple es: "Así es como lo querían los diseñadores de C#". Sin embargo, eso realmente no responde la pregunta. ¿Alguien tiene idea de por qué a los diseñadores de idiomas no les gustó lanzar automáticamente referencias a booleanos (como C/C++/Python)? – Karmastan

+0

Estoy tratando de rastrear una referencia, creo que lo obtuve al hablar con un miembro del equipo de idioma hace un tiempo, lo que realmente no ayuda –

+0

Creo que solo los programadores de C considerarían razonable que null significa falso. False es un valor, null es la falta de un valor. C# lo hace bien, creo. Otros lenguajes que se construyeron sin un tipo booleano o un concepto de puntero (o tipo anulable) simplemente sobrecargaron un int para significar todas estas cosas diferentes. ¿Por qué NULL == es falso y falso == 0? No deberían. – Dolphin

Respuesta

21

Es una característica de diseño específico en el lenguaje C#: if statements accept only a bool.

IIRC Esto es por seguridad: específicamente, para que su primer if (someClass = someValue) no compile.

Edit: Una de las ventajas es que hace innecesaria la convención if (42 == i) ("comparaciones yoda").

+0

Pero en lugar de decir "solo acepta bool" podría decir "no acepta asignación" ... – simendsjo

+1

Sí, encuentro que el comportamiento de C# es preferible aquí, específicamente porque lo protege de ese error común –

+1

La asignación como condición es útil, aunque no tanto en sentencias 'if':' while ((line = Console.ReadLine())! = null) ' –

5

Una cosa que viene a la mente ¿qué pasa con la instancia de un tipo de datos, como int? Int no puede ser nulo, entonces ¿siempre evalúan a verdadero? Podría suponer que int = 0 es falso, pero eso comienza a ser realmente complicado, porque 0 es un valor válido (donde quizás 0 debería evaluarse como verdadero, porque el programador lo configuró) y no solo como un valor predeterminado.
Hay muchos casos extremos donde null no es una opción, a veces es una opción y otras no.

Ponen cosas como esta para proteger al programador de cometer errores. Va a lo largo de la misma línea de por qué no se puede hacer fracasar en las declaraciones de casos.

+1

+1 NULL significa que el valor es desconocido o falta valor o no se ha asignado aún el valor, etc., no significa FALSO, semánticamente no son lo mismo. Siempre pienso que tratar a NULL como FALSO es un mal diseño de lenguaje. – Liwen

+0

@Liwen Estoy de acuerdo. En la superficie, parece que podría tener sentido, pero hay demasiadas posibilidades en las que nulo y falso diferirán. – kemiller2002

+0

Pero un tipo de valor no es un tipo de referencia y no puede ser nulo. No estoy diciendo que todos los tipos posibles que no sean falsos deberían ser verdaderos ... – simendsjo

4

Por lo que yo sé, esta es una característica que se ve en los lenguajes dinámicos, que # C no es (por la especificación del lenguaje if sólo acepta bool o una expresión que se evalúa como bool).

no creo que es razonable suponer que null es false en cada caso. Tiene sentido en algunos casos, pero no en otros. Por ejemplo, suponga que tiene un indicador que puede tener tres valores: conjunto, unset y sin inicializar. En este caso, conjunto sería true, desarmar habría false y no inicializado habría null. Como puede ver, en este caso el significado de null no es false.

+1

mal escrito ≠ tipeado dinámicamente. C++ evalúa 'NULL' (una macro) a' 0', que luego evalúa como 'false' en la sentencia' if'. – strager

+1

No estaba hablando de 'NULL'. Estaba hablando de 'null'. No veo cómo mi declaración original es incorrecta. Normalmente se ve 'if (someVarThatCouldBeNull)' en lenguajes dinámicos. –

+0

Estoy de acuerdo, Vivin. Yo diría que el concepto de nulo no existe en C++. O más bien, el concepto de una variable sin valor (es decir, nulo en C#) no existe en C++. Una variable siempre tendrá un valor, simplemente no se sabe qué es a menos que la inicialices tú mismo. Como señala Straight, NULL en C++ es solo una macro para representar 0, nada más. No hay reglas especiales de compilación a su alrededor. –

19

"Creo que es bastante razonable suponer que significa nula falsa"

No en C#.falso es una estructura booleana, un tipo de valor. Los tipos de valor no pueden tener un valor nulo. Si quería hacer lo que has logrado, habría que crear convertidores de encargo de su tipo particular de booleano:

public class MyClass 
{ 
    public static implicit operator bool(MyClass instance) 
    { 
     return instance != null; 
    } 
} 

Con lo anterior, podría entonces hacer:

if (instance) { 

} 

etc.

+0

También podría utilizar los operadores verdadero o falso, aunque son un poco oscuros: http://msdn.microsoft.com/en-us/library/6x6y6z4d%28VS.80%29.aspx –

+0

En una nota lateral, una consecuencia interesante de usar los operadores verdadero y falso es que un estado particular podría ser verdadero, falso, ninguno o ambos. Esto significa que un tipo que implementa los operadores verdadero y falso podría satisfacer la expresión 'Debug.Assert (x &&! X)' –

+0

Esto es lo que estaba buscando, tengo un objeto de estado y quería poder 'si (estado) {} 'en lugar de' if (status.isSuccess()) {} '. Todavía no estoy seguro de si es una buena idea, pero ahora puedo hacerlo. –

5

sólo tiene que utilizar si (Convert.ToBoolean (algunaClase))

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

Parámetros

valor Tipo: System.Object un objeto que implementa la interfaz IConvertible, o nulo. Valor devuelto

Tipo: System.Boolean verdadera o falsa, que refleja el valor devuelto por invocando el método IConvertible.ToBoolean para el tipo subyacente de valor. Si el valor es nulo, el método devuelve falso

2

C# no realiza una conversión del parámetro, como lo hace C++. Necesita convertir explícitamente el valor en un valor booleano, si desea que la instrucción if acepte el valor.

13

"Creo que es bastante razonable suponer que significa nula falsa"

No estoy de acuerdo. En mi humilde opinión, la mayoría de las veces, falso significa "no". Null significa "no sé"; es decir, completamente indeterminado.

+3

+1 - ¿NULL * ever * significa falso? No puedo pensar en ningún ejemplo de una tecnología que se implemente de esta manera. Puede haber algunos que implícitamente permitan comparaciones, pero afaik, null nunca significa falso. – womp

+0

Si bien no soy un experto en muchos idiomas diferentes, creo que NULL probablemente solo "signifique" falso en un lenguaje que no maneje NULL correctamente desde el principio. –

3

Porque nulo y falso son cosas diferentes.

Un ejemplo perfecto es bool? foo

Si el valor de foo es verdadero, entonces su valor es verdadero.
Si el valor de foo es falso, entonces su valor es falso
Si foo no tiene nada asignado, su valor es nulo.

Estas son tres condiciones lógicamente separadas.

Piense otra manera
"¿Cuánto dinero le debo?"
" Nada" y "no tengo esa información" son dos respuestas claramente separadas.

+0

+1 por un buen punto, pero aún así ... ¿Si intentas evaluar un bool? o bien tienes que lanzarlo a un bool y potencialmente obtener un error de tiempo de ejecución, o usar == verdadero/falso para evaluarlo ... bool? no es un tipo de referencia como mi pregunta, sigue siendo un tipo de valor – simendsjo

+1

Como nota al margen, se supone que una computadora debe saber las respuestas a las preguntas sobre datos y probablemente debería indicar un error si algo "no puede determinarse". – Victor

3

¿Cuál es la razón nula no evaluar a falso en condicionales?

pensé por primera vez acerca de las asignaciones a evitar el error de utilizar = en lugar de ==

Esa no es la razón.Sabemos esto porque si las dos variables que se comparan resultan ser de tipo bool entonces el código se compila alegremente:

bool a = ... 
bool b = ... 

if (a = b) 
    Console.WriteLine("Weird, I expected them to be different"); 

Si b es cierto, se imprime el mensaje (y a ahora es cierto, por lo que la posterior depuración experiencia consistente con el mensaje, confundiendo de este modo aún más ...)

la razón null no se puede convertir en bool es simplemente que C# evita la conversión implícita menos que sea solicitado por el diseñador de un tipo definido por el usuario. El libro de historia de C++ está lleno de historias dolorosas causadas por las conversiones implícitas.

+0

Ya he actualizado mi pregunta con esta de su comentario anterior. El argumento de conversión implícita es el mejor que he escuchado hasta ahora. – simendsjo

1

es simplemente el sistema de tipos de C# en comparación con lenguajes como PHP, Perl, etc.

Una condición sólo acepta valores Boolean, null no tiene el tipo Boolean por lo que no funciona allí.

En cuanto al ejemplo NULL en C/C++ que mencionas en otro comentario, hay que decir que ni C ni C++ tienen un tipo booleano (afair C++ generalmente tiene un tipocast para bool que se resuelve en un int, pero eso es otro materia) y tampoco tienen referencias nulas, solo NULL (=> 0) -pointers.

Por supuesto, los diseñadores del compilador podría aplicar una conversión automática para cualquier tipo anulable a booleano pero eso sería causar otros problemas, es decir:

Suponiendo que foo es nonull:

if (foo) 
{ 
    // do stuff 
} 

Qué estado de foo es cierto?
Siempre si no es nulo?
Pero, ¿y si quieres que tu tipo sea convertible a booleano (es decir, de tu clase tri-estado o de lógica cuántica)?

Eso significaría que tendría dos conversiones diferentes para bool, lo implícito y lo explícito, que se comportarían de manera diferente.

Ni siquiera se atreven a imaginar lo que debe suceder si lo hace

if (!!foo) // common pattern in C to normalize a value used as boolean, 
      // in this case might be abused to create a boolean from an object 
{ 
} 

creo que el (foo == null) forzada es buena ya que también añade claridad a su código, es más fácil de entender lo que realmente comprobar si hay .

3

Estructuralmente, la mayoría de las personas que "no pueden pensar en ninguna razón tecnológica nula deben ser iguales a las falsas".

El código es operado por las CPU. La mayoría de las CPU (si no todas) tienen bits, grupos de bits y interpretaciones de grupos de bits. Dicho esto, algo puede ser 0, 1, byte, word, dword, qword y así sucesivamente.

Tenga en cuenta que en la plataforma x86, los bytes son octetos (8 bits), y las palabras suelen ser de 16 bits, pero esto no es necesario. Las CPU antiguas tenían palabras de 4 bits, e incluso los controladores embebidos de gama baja de hoy a menudo usan como 7 o 12 bits por palabra.

Dicho esto, algo es "igual", "cero", "mayor", "menos", "mayor o igual" o "menos o igual" en el código máquina. No existe tal como null, false o true.

Como convención, true es 1, false es 0, y un puntero null es o bien 0x00, 0x0000, 0x00000000, o 0x0000000000000000, dependiendo de bus de direcciones anchura.

C# es una de las excepciones, ya que es un tipo indirecto, donde los dos valores posibles 0 y 1 no son un valor inmediato, pero un índice de una estructura (creo enum en C, o PTR en x86 montaje).

Esto es por diseño.

Es importante señalar, sin embargo, que tales decisiones de diseño son elaborados decisiones, mientras que el tradicional sencillo manera, es asumir que 0, null y false son iguales.

Cuestiones relacionadas