2011-10-05 13 views
33

Spiegare perché questo test è superato?Operazioni matematiche con null

[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); 
} 

Non capisco come questo codice compili anche.

Sembra che ogni espressione matematica con resi nulli Nullable<T> (ad esempio 10/null è un Nullable<int>). Ma non vedo i metodi dell'operatore nella classe Nullable<T>. Se questi operatori sono presi da int, perché l'ultima asserzione non fallisce?

risposta

26

Da MSDN:

Gli operatori unari e binari predefiniti e eventuali operatori definiti dall'utente che esistono per i tipi di valore possono essere utilizzati anche per tipi nullable. Questi operatori producono un valore nullo se gli operandi sono nulli; in caso contrario, l'operatore utilizza il valore contenuto per calcolare il risultato.

Ecco perché tutti i test sono passati, tra cui l'ultimo - non importa quale sia il valore operando è, se un altro operando è null, allora il risultato è null.

+5

Nota che '==' ha regole leggermente diverse qui; se * entrambi * sono nulli, è 'vero' –

+4

Sì, e lo stesso vale per'! = 'per quanto ne so - se uno è nullo e l'altro no, allora il risultato è' true'. – Andrei

13

Gli operatori per Nullable<T> sono i cosiddetti operatori "sollevati"]; il compilatore C# prende gli operatori disponibili per T e applica una serie di regole predefinite; ad esempio, con +, lo + sollevato è null se uno degli operandi è nullo, altrimenti la somma dei valori interni. Re l'ultimo; di nuovo, la divisione è definita come null se uno degli operandi è null - mai esegue la divisione.

+0

Potrebbe essere che il compilatore lo traduca semplicemente in qualcos'altro? Vedi la mia risposta. –

+0

@ Martin Ho già commentato la tua risposta p –

+1

@MarcGravell Se la divisione non viene mai eseguita, perché il compilatore non compila 'Assert.That (null/0, Is.Null);'? – altso

1

Suppongo che il compilatore converta zero in Nullable<int> e fornisca l'operatore di divisione sottostante. Poiché il tipo Nullable potrebbe essere nullo, la divisione per 0 non viene rilevata durante la compilazione. La migliore ipotesi è che vogliono che tu sia in grado di eseguire test nulli nei casi in cui si verifica div/0.

1

ho cercato di vedere il codice generato dal codice qui sotto usando riflettore

var myValue = 10/null; 

e il compilatore trasforma in questo:

int? myValue = null; 

E questo voleva compilare, in modo da non puoi ingannarlo:

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

Sì, ma questo semplicemente riafferma la domanda, poiché ** in entrambi i casi ** è il compilatore a farlo (usando le stesse regole) - semplicemente, capita di essere in grado di farlo come valore costante in questo caso. –

+0

Sì, grazie per il suggerimento sulle costanti. – altso

1

Le operazioni in questo elenco restituiscono sempre NULL:

1 + 2 + 3 + NULL 

5 * NULL - 7 

'Home ' || 'sweet ' || NULL 

MyField = NULL 

MyField <> NULL 

NULL = NULL 
+0

Si noti che le risposte di solo collegamento sono scoraggiate (i collegamenti tendono a diventare obsoleti nel tempo). Ti preghiamo di considerare di modificare la tua risposta e di aggiungere una sinossi qui. – bummi

+0

Grazie a bummi per correggermi! – Sohil

+0

Questo non mi sembra C#. Che lingua è questa? – Sam

Problemi correlati