2008-09-15 10 views
5

estoy usando int como un ejemplo, pero esto se aplica a cualquier tipo de valor en .Net.Net 2+: ¿por qué if (1 == null) ya no lanza una excepción de compilador?

En .Net 1 lo siguiente sería lanzar una excepción compilador:

int i = SomeFunctionThatReturnsInt(); 

if(i == null) //compiler exception here 

ahora (en .Net 2 o 3.5) esa excepción se ha ido.

sé por qué esto es:

int? j = null; //nullable int 

if(i == j) //this shouldn't throw an exception 

El problema es que debido a int? es anulable y int tiene ahora una conversión implícita a int?. La sintaxis anterior es magia de compilador. Realmente lo estamos haciendo:

Nullable<int> j = null; //nullable int 

//compiler is smart enough to do this 
if((Nullable<int>) i == j) 

//and not this 
if(i == (int) j) 

Así que ahora, cuando hacemos i == null obtenemos:

if((Nullable<int>) i == null) 

Dado que C# compilador está haciendo la lógica para calcular esto de todos modos por qué no puede ser lo suficientemente inteligente como para no hacerlo cuando se trata de valores absolutos como null?

Respuesta

3

No creo que esto sea un problema de compilación per se; un valor entero nunca es nulo, pero la idea de equipararlos no es inválida; es una función válida que siempre devuelve falso. Y el compilador sabe; el código

bool oneIsNull = 1 == null; 

compila, pero da una advertencia del compilador: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type '<null>'.

Así que si quiere recuperar el error del compilador, vaya a las propiedades del proyecto y active 'tratar advertencias como errores' para este error, y comenzará a verlas nuevamente como problemas de compilación.

1

El compilador aún genera una advertencia cuando compara el tipo que no admite nulos con el valor nulo, que es exactamente como debería ser. Puede ser que su nivel de advertencia sea demasiado bajo o que esto haya cambiado en versiones recientes (solo lo hice en .net 3.5).

3

Odd ... compilar esto con VS2008, que apuntan a .NET 3.5:

static int F() 
    { 
     return 42; 
    } 

    static void Main(string[] args) 
    { 
     int i = F(); 

     if (i == null) 
     { 
     } 
    } 

me sale un compilador de advertencia

warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?' 

y genera el siguiente IL ... que presumiblemente el JIT optimizará lejos

L_0001: call int32 ConsoleApplication1.Program::F() 
    L_0006: stloc.0 
    L_0007: ldc.i4.0 
    L_0008: ldc.i4.0 
    L_0009: ceq 
    L_000b: stloc.1 
    L_000c: br.s L_000e 

¿Se puede publicar un fragmento de código?

+0

El compilador detecta correctamente que nunca es cierto, al igual que si hubiera hecho 1 == 2. ¿Es lo suficientemente inteligente como para saber que int se puede convertir implícitamente en int? y ese int? se puede comparar con nulo. Sospecho que el optimizador es lo suficientemente inteligente como para desmantelar todo el bloque. – Keith

0

La advertencia es nueva (3.5 Creo) - el error es el mismo que si hubiera hecho 1 == 2, que es lo suficientemente inteligente para detectar como nunca.

Sospecho que con 3.5 optimizaciones completas se eliminará toda la declaración, ya que es bastante inteligente con evaluaciones nunca verdaderas.

Aunque podría querer 1==2 compilar (para desactivar un bloque de funciones mientras pruebo algo más, por ejemplo) no quiero 1==null para.

0

Debe ser un error en tiempo de compilación, porque los tipos son incompatibles (los tipos de valores nunca pueden ser nulos). Es bastante triste que no lo sea.

+0

Lea toda la pregunta, explico por qué ocurre. La pregunta es por qué no puede tratarse como un caso especial. – Keith

+0

Cuando digo "debería" me refiero a que existe un imperativo moral, no es lo que espero que haga el compilador. El razonamiento que describes no es para nada convincente; deberían hacer de esto una falla de compilación estática. – DrPizza

1

El marco 2.0 introdujo el tipo de valor anulable. Aunque la constante literal "1" nunca puede ser nula, su tipo subyacente (int) ahora se puede convertir a un tipo int Nullable. Supongo que el compilador ya no puede suponer que los tipos int no pueden contener nulos, incluso cuando es una constante literal. Obtengo una advertencia al compilar 2.0:

Advertencia 1 El resultado de la expresión es siempre 'falso' ya que un valor de tipo 'int' nunca es igual a 'nulo' de tipo 'int' '

+0

Como dije, ¿el compilador sabe que int se puede convertir implícitamente en int? y int? se puede comparar con nulo. La advertencia es general para cualquier comparación nunca verdadera. 1 == 2 arrojará la misma advertencia. – Keith

Cuestiones relacionadas