.Neto 2+:¿Por qué if( 1 == null ) ya no genera una excepción del compilador?
-
09-06-2019 - |
Pregunta
Estoy usando int
como ejemplo, pero esto se aplica a cualquier tipo de valor en .Net
En .Net 1, lo siguiente generaría una excepción del compilador:
int i = SomeFunctionThatReturnsInt();
if( i == null ) //compiler exception here
Ahora (en .Net 2 o 3.5) esa excepción ha desaparecido.
Sé por qué esto es:
int? j = null; //nullable int
if( i == j ) //this shouldn't throw an exception
El problema es que porque int?
es anulable y int
ahora tiene un elenco implícito para int?
.La sintaxis anterior es mágica del compilador.Realmente 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 lo hagamos i == null
obtenemos:
if( (Nullable<int>) i == null )
Dado que C# está utilizando la lógica del compilador 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
?
Solución
No creo que esto sea un problema del compilador. 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 lo 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>'
.
Entonces, si desea recuperar el error del compilador, vaya a las propiedades del proyecto y active "tratar las advertencias como errores" para este error, y comenzará a verlos nuevamente como problemas que interrumpen la compilación.
Otros consejos
Extraño ...compilando esto con VS2008, apuntando a .NET 3.5:
static int F()
{
return 42;
}
static void Main(string[] args)
{
int i = F();
if (i == null)
{
}
}
Recibo una advertencia del compilador
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á
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
¿Puedes publicar un fragmento de código?
El compilador todavía genera una advertencia cuando se compara un tipo que no acepta valores NULL con NULL, que es exactamente como debería ser.Puede ser que su nivel de advertencia sea demasiado bajo o que esto se haya cambiado en versiones recientes (solo lo hice en .net 3.5).
El marco 2.0 introdujo el tipo de valor que acepta valores NULL.Aunque la constante literal "1" nunca puede ser nula, su tipo subyacente (int) ahora se puede convertir a un tipo int anulable.Supongo que el compilador ya no puede asumir que los tipos int no admiten valores NULL, incluso cuando es una constante literal.Recibo una advertencia al compilar 2.0:
Advertencia 1 El resultado de la expresión siempre es 'falso' ya que un valor de tipo 'int' nunca es igual a 'nulo' de tipo 'int?'
La advertencia es nueva (creo que 3.5): el error es el mismo que si lo hubiera hecho 1 == 2
, que es lo suficientemente inteligente como para detectar que nunca es cierto.
Sospecho que con las optimizaciones 3.5 completas se eliminará toda la declaración, ya que es bastante inteligente con evaluaciones que nunca son verdaderas.
Mientras que yo podría querer 1==2
para compilar (para desactivar un bloque de funciones mientras pruebo algo más, por ejemplo) no quiero 1==null
a.
Debería 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.