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?

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top