2012-02-29 27 views
19

¿Alguien tiene información concreta sobre cómo C# maneja las comparaciones con los tipos Nullable<T> cuando un lado de la comparación es nulo?¿Cómo manejan los tipos anulables los valores nulos con los operadores de comparación?

Como entiendo al experimentar con el compilador, parece que la comparación siempre devuelve falso, pero no puedo encontrar ninguna documentación para respaldarlo. ¿Es esta una característica real del lenguaje (y por lo tanto algo con lo que puedo contar), o es este un detalle de implementación que podría cambiar en futuras versiones?

En otras palabras, ¿el siguiente método devuelve verdadero implica y.HasValue, y puede indicarme alguna documentación que demuestre que lo hace?

public bool foo(int x, int? y) 
    { 
     return x < y; 
    } 
+1

¿Por qué esperaría que null * ever * comparase igual a * cualquier * valor? –

Respuesta

43

¿Alguien tiene información concreta sobre la forma en C# maneja las comparaciones con los tipos anulables cuando un lado de la comparación es nula?

Sí - la especificación del lenguaje C#, sección 7.3.7. En este caso, se trata de un operador relacional:

Para los operadores de relación < > <= >= una forma elevada de un operador existe si los tipos de los operandos son ambos tipos no anulable y si el tipo de resultado es bool. La forma levantada se construye agregando un modificador único ? a cada tipo de operando. El operador elevado produce el valor false si uno o ambos operandos son nulos. De lo contrario, el operador levantado desenvuelve los operandos y aplica el operador subyacente para producir el resultado bool.

Existen secciones con un perfil similar para otros operadores.

Cuando tenga dudas sobre cómo funciona algún aspecto del lenguaje (y si está garantizado o es específico de la implementación), la especificación del lenguaje C# debe ser su primer puerto de escala.

+3

Para descargar las especificaciones para leer: http://www.microsoft.com/download/en/details.aspx?id=7029 –

+0

Esta parte de la sección 4.1.10 de la especificación también me ayudó a entender todo esto: "Las conversiones implícitas son disponible [...] de T a T? " – andrej351

+0

Jon, esto puede ser una posibilidad remota, pero ¿sabes por qué ***, para los operadores '<=' and '> =', * El operador levantado produce el valor 'falso' si uno o ambos operandos son' null' * "? Me parece extraño que '(null == null) == true', yet' (null <= null) == false'. –

5

Si uno de los valores es nula, la comparación será falsa (a excepción de !=)

Al realizar comparaciones con los tipos anulables, si el valor de una de los tipos anulables es null y el otro no, todas las comparaciones se evalúan como falsas excepto por! = (no igual). Es importante no suponer que debido a que una comparación particular devuelve falso, el caso opuesto devuelve verdadero. En el siguiente ejemplo, 10 no es mayor que, menor que, ni igual a nulo. ¡Solo num1! = Num2 se evalúa como verdadero.

MSDN Source

+0

No sé si los resultados son diferentes. Sin embargo, esa cita se trata de comparar dos tipos Nullable. – Joe

2

MSDN tiene que decir lo siguiente al respecto:

Al realizar comparaciones con los tipos anulables, si el valor de uno de los tipos anulables es nula y el otro no lo es, todas las comparaciones resultado false excepto por! = (no igual)."

http://msdn.microsoft.com/en-us/library/2cf62fcy(v=vs.100).aspx

Éstos son los ejemplos de código proporcionados:

int? num1 = 10; 
int? num2 = null; 
if (num1 >= num2) 
{ 
    Console.WriteLine("num1 is greater than or equal to num2"); 
} 
else 
{ 
    // This clause is selected, but num1 is not less than num2. 
    Console.WriteLine("num1 >= num2 returned false (but num1 < num2 also is false)"); 
} 

if (num1 < num2) 
{ 
    Console.WriteLine("num1 is less than num2"); 
} 
else 
{ 
    // The else clause is selected again, but num1 is not greater than 
    // or equal to num2. 
    Console.WriteLine("num1 < num2 returned false (but num1 >= num2 also is false)"); 
} 
if (num1 != num2) 
{ 
    // This comparison is true, num1 and num2 are not equal. 
    Console.WriteLine("Finally, num1 != num2 returns true!"); 
} 
// Change the value of num1, so that both num1 and num2 are null. 
num1 = null; 
if (num1 == num2) 
{ 
    // The equality comparison returns true when both operands are null. 
    Console.WriteLine("num1 == num2 returns true when the value of each is null"); 
} 
0

Si no hay un CompareTo específico implementado, entonces mi investigación me dice que el objeto va a utilizar el CompareTo (objeto) En el caso de un int, puede compararlo con un int o un objeto. En este caso, solo verifica si el objeto es nulo o no. Aquí hay un enlace al int CompareTo (objeto), detalla el motivo de los resultados de comparar un int y un objeto.

http://msdn.microsoft.com/en-us/library/system.int32.aspx

no puedo encontrar nada con seguridad, pero no veo nada que indique que el marco .NET se amplió para incluir un método para la CompareTo System.Nullable<T> para cada <T>.

Si fuera mi código, me protegería y extendería la clase Int para incluir un CompareTo.

0

sé que llego tarde, pero voy a tirar mis dos centavos en

Si falla la memoria, las reglas para un comparador son los siguientes:.

  • Si X e Y son nulos , devuelve 0 (son iguales).
  • Si x es nulo, y y no lo es, devuelve -1 (x es menor que y).
  • Si x no es nulo, y y es nulo, devuelve 1 (x es mayor que y).

Para todos los valores no nulos:

  • Cuando el valor de x se evalúa como menor que y, devuelven -1.
  • Cuando el valor de x evalúa y, devolverá 0.
  • Cuando el valor de x se evalúa como mayor que y, devuelva 1.

Para todos los intentos y propósitos, un Anulable <T> evalúa nulo cuando no tiene valor. Entonces las reglas son esencialmente las mismas. Al menos, así es como escribí mis comparadores. Si lo estoy haciendo mal, entonces, ¡Dios santo, lo estoy haciendo mal, y espero que alguien me diga cómo arreglarlo!

Cuestiones relacionadas