¿Por qué el operador es devuelve falso cuando se le da nulo?

Me parece que el operador es un poco inconsistente.

 bool Test() { // Returns false, but should return true. return null is string; } 

Se espera que el valor null pertenezca a cualquier tipo de referencia (o anulable). Y, de hecho, la especificación del lenguaje C # dice algo que respalda esta hipótesis, por ejemplo (6.1.6 conversiones de referencia implícitas):

Las conversiones de referencia implícitas son:

• Desde el literal nulo hasta cualquier tipo de referencia.

La descripción (7.10.10 El operador is) del operador is comienza diciendo que la expresión (E is T) dará como resultado verdadero cuando existe una conversión de referencia de E a T , pero luego los autores continúan excluyendo explícitamente el caso cuando E es el literal null o tiene un valor null .

¿Por qué hacen eso? Para mí, parece contradictorio.

Esta pregunta fue el tema de mi blog el 30 de mayo de 2013 . Gracias por la gran pregunta!


Estás mirando un camino vacío.

Alguien te pregunta: “¿puede tu entrada tener un Honda Civic?”

Sí. Sí puede.

Alguien te señala en un segundo camino de entrada. También está vacío. Preguntan “¿Puede el contenido actual de mi camino de entrada en su entrada?”

Si obviamente. ¡Ambas entradas están vacías! Así que claramente el contenido de uno puede caber en el otro, porque no hay contenido de ninguno en primer lugar.

Alguien te pregunta: “¿Tiene tu camino un Honda Civic?”

No, no lo hace.

Estás pensando que el operador is responde a la segunda pregunta: dado este valor, ¿cabe en una variable de ese tipo? ¿Encaja una referencia nula en una variable de este tipo? Sí lo hace.

Esa no es la pregunta que responde el operador. La pregunta que responde el operador es la tercera pregunta. y is X no pregunta “¿ es un valor legal de una variable de tipo X ? ” Pregunta ” ¿Es y una referencia válida para un objeto de tipo X ? ” Dado que una referencia nula no es una referencia válida a ningún objeto de ninguna tipo, la respuesta es “no”. Esa entrada está vacía; no contiene un Honda Civic.

Otra forma de verlo es que y is X la pregunta “si dijera y as X , ¿obtendría un resultado no nulo? Si y es nulo, ¡claramente la respuesta es no!


Para ver un poco más profundo en tu pregunta:

Se espera que el valor nulo pertenezca a cualquier tipo de referencia (o anulable)

Uno estaría implícitamente asumiendo que un tipo es un conjunto de valores , y que la compatibilidad de asignación de un valor y con una variable de tipo X no es más que verificar si y es un miembro del conjunto x .

Aunque esa es una forma extremadamente común de mirar los tipos, esa no es la única forma de ver los tipos, y no es la forma en que C # mira los tipos. Las referencias nulas son miembros de ningún tipo en C #; la compatibilidad de asignación no es simplemente verificar un conjunto para ver si contiene un valor. El hecho de que una referencia nula sea compatible con una asignación de referencia de tipo X no significa que null sea miembro de tipo X. La relación “es compatible con la asignación” y la relación “es un miembro de tipo” obviamente tiene una gran cantidad de se superponen, pero no son idénticos en el CLR.

Si le interesan las reflexiones sobre la teoría de tipos, consulte mis artículos recientes sobre el tema:

¿Qué es esto que llamas un “tipo”? Parte uno

¿Qué es esto que llamas un “tipo”? La segunda parte

El literal null se puede asignar a cualquier tipo de referencia. No es un tipo en sí mismo. Es un literal especial que representa una referencia nula.

En el caso en que eso is true cuando se pasa un null , ¿qué podría hacer con el literal null ? Nada, es null . ¿De qué serviría volver true excepto por cuestiones confusas?


De todos modos, en términos de lo intuitivo que es, lea el código en inglés y dígame:

 null is string; 

Cuando veo eso, parece estar haciendo la pregunta is "nothing" a string? . Mi intuición me dice que no, que no es nothing .

Creo que null is string devuelve false es muy intuitiva. Null no significa nada, y definitivamente no es una cadena. Por lo tanto, debe devolver falso. Si bien es una elección de los diseñadores de idiomas, es muy intuitiva cuando se considera el significado del mundo real de null.

http://msdn.microsoft.com/en-us/library/scekt9xw%28v=vs.71%29.aspx

Una expresión is es evaluada como verdadera si se cumplen las dos condiciones siguientes:

  • la expresión no es nula.
  • la expresión se puede convertir a tipo. Es decir, una expresión moldeada de la forma (tipo (expresión) se completará sin lanzar una excepción. Para obtener más información, consulte 7.6.6 Expresiones de molde.

Como una cuestión práctica, tener “nulo es T == falso” me ahorra escribir código extra:

En lugar de tener que decir

 if (X != null && X is Foo) {} 

Solo puedo decir

 if (X is Foo) {} 

y termine con esto.

el valor null

He citado esto de su pregunta porque parece llegar al meollo del asunto. null no es un valor, es la ausencia de un valor. El propósito de is para mí responder a la pregunta:

Si selecciono E a T , ¿obtendré con éxito una T ?

Ahora, aunque puedes convertir null en T sin error , después de hacerlo no tienes ” T “, todavía no tienes nada. Por lo tanto, no es el caso que null “es” una T , por is devuelve falso.

En Java hay un operador que hace exactamente lo mismo, pero tiene un nombre mucho más largo: instanceof . Aquí es muy intuitivo que la null instanceof String devuelve falso, porque null no es una instancia de nada, y mucho menos una String . Entonces, cuando se usa null la versión de Java es un poco más intuitiva.

Sin embargo, ambos operadores devuelven la verdad cuando se les pide que revisen toda la jerarquía también. P.ej. si instancia de String es un Object . Y aquí está Java que es un poco menos intuitivo (porque una instancia tiene realmente un tipo muy específico) y C # ‘s es más intuitivo (porque cada String es un Object el interior).

En pocas palabras: si tratas de describir una lógica bastante avanzada en una palabra, es probable que tengas pocas personas confundidas, de una u otra forma. Parece que la mayoría de la gente estuvo de acuerdo en un significado y aquellos que no estuvieron de acuerdo, tuvieron que adaptarse.