visual studio microsoft español descargar community c# .net language-lawyer

c# - microsoft - visual studio installer



¿Cuál es el tipo de literal nulo? (3)

A pesar de no tener ningún tipo de tiempo de ejecución, el null se puede convertir a un tipo en tiempo de compilación, como muestra este ejemplo.

En tiempo de ejecución, puede encontrar que la variable stringAsObject contiene una string , no solo un object , pero no puede encontrar ningún tipo para las variables nullString y nullStringAsObject .

public enum Answer { Object, String, Int32, FileInfo }; private Answer GetAnswer(int i) { return Answer.Int32; } private Answer GetAnswer(string s) { return Answer.String; } private Answer GetAnswer(object o) { return Answer.Object; } [TestMethod] public void MusingAboutNullAtRuntimeVsCompileTime() { string nullString = null; object nullStringAsObject = (string)null; object stringAsObject = "a string"; // resolved at runtime Expect.Throws(typeof(ArgumentNullException), () => Type.GetTypeHandle(nullString)); Expect.Throws(typeof(ArgumentNullException), () => Type.GetTypeHandle(nullStringAsObject)); Assert.AreEqual(typeof(string), Type.GetTypeFromHandle(Type.GetTypeHandle(stringAsObject))); Assert.AreEqual(typeof(string), stringAsObject.GetType()); // resolved at compile time Assert.AreEqual(Answer.String, this.GetAnswer(nullString)); Assert.AreEqual(Answer.Object, this.GetAnswer(nullStringAsObject)); Assert.AreEqual(Answer.Object, this.GetAnswer(stringAsObject)); Assert.AreEqual(Answer.Object, this.GetAnswer((object)null)); Assert.AreEqual(Answer.String, this.GetAnswer((string)null)); Assert.AreEqual(Answer.String, this.GetAnswer(null)); } // Uncommenting the following method overload // makes the last statement in the test case ambiguous to the compiler // private Answer GetAnswer(FileInfo f) { return Answer.FileInfo; }

re oído todo, me pregunto cuál es el tipo de literal null en C #?

En Java, el literal null es del tipo nulo especial :

También hay un tipo nulo especial, el tipo de la expresión null , que no tiene nombre. Debido a que el tipo nulo no tiene nombre, es imposible declarar una variable del tipo nulo o convertir al tipo nulo. La referencia nula es el único valor posible de una expresión de tipo nulo. La referencia nula siempre se puede convertir a cualquier tipo de referencia.

En C ++ 11, hay nullptr (la versión recomendada del antiguo amigo NULL ), que es de tipo std::nullptr_t .

Busqué en MSDN sobre C #, pero la specification no parece decir nada al respecto.


ACTUALIZACIÓN: Esta pregunta fue el tema de mi blog en julio de 2013. ¡ Gracias por la gran pregunta!

La respuesta de J.Kommer es correcta (¡y buena para ellos en lo que evidentemente fue una gran cantidad de especulación!) Pero pensé que agregaría un poco de perspectiva histórica.

Cuando Mads y yo estábamos clasificando la redacción exacta de varias partes de la especificación para C # 3.0, nos dimos cuenta de que el "tipo nulo" era extraño. Es un "tipo" con un solo valor. Es un "tipo" del que Reflection no sabe nada. Es un "tipo" que no tiene un nombre, que GetType nunca devuelve, que no puede especificar como el tipo de una variable o campo local o algo así. En resumen, realmente es un "tipo" que está solo para hacer que el sistema de tipos esté "completo", de modo que cada expresión en tiempo de compilación tenga un tipo.

Excepto que C # ya tenía expresiones que no tenían tipo: los grupos de métodos en C # 1.0, los métodos anónimos en C # 2.0 y las lambdas en C # 3.0 no tienen ningún tipo. Si todas esas cosas no pueden tener ningún tipo, nos dimos cuenta de que "nulo" tampoco necesita tener un tipo. Por lo tanto, eliminamos las referencias al "tipo nulo" inútil en C # 3.0.

Como detalle de implementación, todas las implementaciones de Microsoft de C # 1.0 a 5.0 tienen un objeto interno para representar el "tipo nulo". También tienen objetos para representar los tipos no existentes de lambdas, métodos anónimos y grupos de métodos. Esta elección de implementación tiene una serie de ventajas y desventajas. En el lado pro, el compilador puede pedir el tipo de expresión y obtener una respuesta. En el lado negativo, significa que a veces los errores en el análisis de tipo que realmente deberían haber bloqueado el compilador en su lugar causan cambios semánticos en los programas. Mi ejemplo favorito de eso es que es posible en C # 2.0 usar la expresión ilegal "null ?? null"; debido a un error, el compilador no lo marca como un uso erróneo del ?? operador, y continúa inferiendo que el tipo de esta expresión es "el tipo nulo", aunque no sea un literal nulo. Eso luego continúa causando muchos otros errores de flujo descendente a medida que el analizador de tipos intenta dar sentido al tipo.

En Roslyn probablemente no usaremos esta estrategia; en su lugar, simplemente vamos a hornear en la implementación del compilador que algunas expresiones no tienen tipo.


Según la especificación de lenguaje C # de ECMA :

9.4.4.6 El literal nulo:

El tipo de un literal nulo es el tipo nulo (§11.2.7).

11.2.7 El tipo nulo:

El literal nulo (§9.4.4.6) se evalúa al valor nulo, que se utiliza para denotar una referencia que no apunta a ningún objeto o matriz, o la ausencia de un valor. El tipo nulo tiene un valor único, que es el valor nulo. Por lo tanto, una expresión cuyo tipo es el tipo nulo se puede evaluar solo al valor nulo. No hay forma de escribir explícitamente el tipo nulo y, por lo tanto, no hay forma de usarlo en un tipo declarado. Además, el tipo nulo nunca puede ser el tipo inferido para un parámetro de tipo (§25.6.4)

Entonces, para responder a su pregunta, nulo es su propio tipo, el tipo nulo.

Aunque es extraño que no se mencione en la specification o en la specification C # 3.0, se menciona en la descripción general de C # 3.0 , la especificación del lenguaje ECMA C # y la especificación del lenguaje C # 2.0 .