2010-01-28 8 views

risposta

10

Questo è conforme alle specifiche per operatori binari sollevati. Da §7.2.7:

Per gli operatori binari

+ - */% & |^<< >>

una forma alzato di un operatore esiste se i tipi di operando e di risultato sono tutti tipi di valore non annullabili. La forma sollevata viene creata aggiungendo un singolo modificatore ? a ciascun operando e al tipo di risultato. L'operatore sollevato produce un valore nullo se uno o entrambi gli operandi sono nulli (ad eccezione degli operatori & e | del tipo bool ?, come descritto in §7.10.3). In caso contrario, l'operatore sollevato sposta gli operandi, applica l'operatore sottostante e avvolge il risultato.

Il ragionamento è questo: si sta per pensare null per un tipo nullable nel senso di "Io non so che cosa il valore è". Qual è il risultato di "Non so" più uno? "Non lo so." Pertanto, il risultato dovrebbe essere null.

+0

La tua logica è ben formulata, ma in realtà dovrebbe generare un'eccezione. Pensa + al modo sintatticamente più semplice di eseguire number.Plus (2). Dovrebbe sicuramente generare un'eccezione se il numero è nullo o può facilmente causare un comportamento imprevisto. –

+0

Ancora peggio, se hai un numero e aggiungi null a esso, diventerà nullo. –

0

Purtroppo no. Il X in x = X + 1 è nullo come nella prima riga, quindi si aggiunge 1 a null, che equivale a null.

Come è un int nullable, è possibile utilizzare x.HasValue per verificare se ha un valore, quindi x.Value per ottenere il valore reale int fuori

2

Perché vi aspettate il compilatore per buttarlo come int quando lo hai dichiarato come Nullable? Il compilatore sta facendo ciò che gli hai detto di fare e null +1 = null.

È necessario eseguire il cast esplicito o controllare x.HasValue prima di tentare di aggiungere un int.

5

Nullables non sono mai effettivamente riferimenti null. Sono sempre riferimenti a oggetti. Le loro classi interne sovrascrivono gli operatori == e =. Se vengono confrontati con null, restituiranno il valore della proprietà HasValue.

+1

La prima frase è corretta. Le due frasi di mezzo non sono corrette. Nullables sono * mai * riferimenti a oggetti. La struttura Nullable non * sovrascrive l'operatore di uguaglianza. Non esiste una cosa come ignorare l'operatore di assegnazione. L'ultima frase è corretta. –

+0

Hai ragione - non l'operatore di assegnazione, ma la conversione implicita da un int. Sono decisamente diversi operatori ma alla fine l'effetto è lo stesso. Grazie per la segnalazione. – rusty

2

La ragione di questo è che il compilatore crea un operatore di 'sollevato' per i tipi nullable - in questo caso si tratta di qualcosa di simile:

public static int? operator +(int? a, int? b) 
{ 
    return (a == null || b == null) ? (int?)null : a.Value + b.Value 
} 

Penso che se si tenta di assegnare il risultato a un non- valore nullable, il compilatore sarà costretto a utilizzare il sovraccarico non annullabile e convertire x in un int.

e.g. int i = x + 1; //throws runtime exception 
+0

effettivamente int i = x + 1 è un errore. int i = (int) (x + 1) genererà un'eccezione se x non ha valore. – Dolphin

0

Indipendentemente dal fatto che x non sia mai effettivamente nullo, non è nemmeno il punto.

Il punto è, quando avete mai visto un NullReferenceException quando si tenta di eseguire un'aggiunta?

Il seguente esempio non genera uno NullReferenceException ed è perfettamente valido.

string hello = null; 
string world = "world"; 
string hw = hello+world; 

Si potrebbe ottenere solo un NullReferenceException se si tenta di accedere a un membro su un oggetto che è nullo.

-1

int? non può mai essere nullo perché è una struttura. Le strutture vivono nello stack e lo stack non gestisce bene null.

Vedi What is a NullPointerException, and how do I fix it?

Inoltre, i tipi nullable hanno 2 proprietà molto utili: HasValue, Valore

Questo codice:

 if (x != null) 
     { 
      return (int) x; 
     } 

Dovrebbe essere riscritta a questo:

 if (x.HasValue) 
     { 
      return x.Value; 
     } 
+0

Questo è completamente errato. Innanzitutto, i tipi di valore non "vivono in pila". I tipi di valore vivono ovunque, nella pila o nell'heap, come il gestore della memoria ritiene opportuno. In secondo luogo, è perfettamente legale avere un riferimento null sullo stack. "string s = null;", c'è un riferimento null sullo stack, nessun problema. –

+1

Apprezzo la correzione. Quando ho iniziato per la prima volta in .NET mi ricordo di averlo fatto: DateTime x = null; e ottenendo questo errore "Il compilatore non può assegnare null a un tipo di valore, null può essere assegnato solo a un tipo di riferimento. struct è un tipo di valore." Ho frainteso il messaggio. L'errore sta parlando delle limitazioni del tipo null-literal e non del valore. Grazie per il meritato schiaffo in testa. – fremis

Problemi correlati