2011-10-05 17 views
33

Por favor, explique por qué pasa esta prueba.Operaciones matemáticas con nulo

[Test] 
public void TestNullOps() 
{ 
    Assert.That(10/null, Is.Null); 
    Assert.That(10 * null, Is.Null); 
    Assert.That(10 + null, Is.Null); 
    Assert.That(10 - null, Is.Null); 
    Assert.That(10 % null, Is.Null); 
    Assert.That(null/10, Is.Null); 
    Assert.That(null * 10, Is.Null); 
    Assert.That(null + 10, Is.Null); 
    Assert.That(null - 10, Is.Null); 
    Assert.That(null % 10, Is.Null); 

    int zero = 0; 
    Assert.That(null/zero, Is.Null); 
} 

No entiendo cómo compila este código.

Parece que cada expresión matemática con retornos nulos Nullable<T> (por ejemplo, 10/null es un Nullable<int>). Pero no veo los métodos de operador en la clase Nullable<T>. Si estos operadores se toman de int, ¿por qué la última afirmación no falla?

Respuesta

26

De MSDN:

Los operadores unarios y binarios predefinidos y cualesquiera operadores definidos por el usuario que existen para los tipos de valor también puede ser utilizada por tipos anulables. Estos operadores producen un valor nulo si los operandos son nulos; de lo contrario, el operador usa el valor contenido para calcular el resultado.

Es por eso que se pasan todas las pruebas, incluida la última, sin importar el valor del operando, si otro operando es null, entonces el resultado es null.

+5

Tenga en cuenta que '==' tiene reglas ligeramente diferentes aquí; si * ambos * son nulos, es 'verdadero' –

+4

Sí, y lo mismo vale para '! =' por lo que sé, si uno es nulo y el otro no, entonces el resultado es 'verdadero'. – Andrei

13

Los operadores para Nullable<T> son operadores denominados "levantados"]; el compilador C# toma los operadores disponibles para T y aplica un conjunto de reglas predefinidas; por ejemplo, con +, el + elevado es null si cualquiera de los dos operandos es nulo, sino la suma de los valores internos. Re el último; de nuevo, la división se define como null si cualquiera de los operandos es null - nunca realiza la división.

+0

¿Podría ser que el compilador simplemente lo traduzca en algo más? Ver mi respuesta –

+0

@Martin Ya comenté su respuesta; p –

+1

@MarcGravell Si la división nunca se realiza, ¿por qué el compilador no compila 'Assert.That (null/0, Is.Null);'? – altso

1

Supongo que el compilador convierte zero en Nullable<int>, y proporciona el operador de división subyacente. Como el tipo Nullable puede ser nulo, la división por 0 no se detecta durante la compilación. La mejor suposición es que quieren que puedas hacer pruebas nulas en los casos en que div/0 está ocurriendo.

1

he intentado ver el código generado a partir del código de abajo usando el reflector

var myValue = 10/null; 

y el compilador lo convierte en esto:

int? myValue = null; 

Y esta costumbre de compilación, así que no puedes engañar a ella:

object myNull = null; 
var myValue = 10/myNull; 
+0

Sí, pero eso solo reafirma la pregunta, ya que ** en ambos casos ** es el compilador que hace esto (usando las mismas reglas) - simplemente, sucede que es capaz de hacerlo como un valor constante en este caso. –

+0

Sí, gracias por su sugerencia sobre las constantes. – altso

1

Las operaciones en esta lista siempre devuelven NULL:

1 + 2 + 3 + NULL 

5 * NULL - 7 

'Home ' || 'sweet ' || NULL 

MyField = NULL 

MyField <> NULL 

NULL = NULL 
+0

Tenga en cuenta que las respuestas de solo enlace no se recomiendan (los enlaces tienden a quedarse obsoletos a lo largo del tiempo). Considere editar su respuesta y agregar una sinopsis aquí. – bummi

+0

¡Gracias bummi por corregirme! – Sohil

+0

Esto no se parece a C#. ¿Qué lenguaje es este? – Sam

Cuestiones relacionadas