In C # perché un operatore condizionale non può eseguire il cast implicitamente su un tipo nullable

Sono curioso di sapere perché un cast implicito fallisce in …

int? someValue = SomeCondition ? ResultOfSomeCalc() : null; 

e perché invece devo eseguire un cast esplicito

 int? someValue = SomeCondition ? ResultofSomeCalc() : (int?)null; 

Mi sembra che il compilatore abbia tutte le informazioni necessarie per prendere una decisione implicita sul casting, no?

La sezione pertinente della specifica C # 3.0 è 7.13, l’operatore condizionale:

Il secondo e il terzo operando dell’operatore?: Controllano il tipo di espressione condizionale. Sia X e Y i tipi del secondo e del terzo operando. Poi,

Se X e Y sono dello stesso tipo, allora questo è il tipo del condizionale Altrimenti, se esiste una conversione implicita (§6.1) da X a Y, ma non da Y a X, allora Y è il tipo di espressione condizionale. Altrimenti, se esiste una conversione implicita (§6.1) da Y a X, ma non da X a Y, X è il tipo di espressione condizionale. Altrimenti, non è ansible determinare alcun tipo di espressione e si verifica un errore in fase di compilazione.

Sono anche seccato che non possa dedurre il tipo basato sul compito, specialmente quando si tratta di un tipo di valore. Ci sono dei motivi però quando entri nelle gerarchie degli oggetti.

Se “ResultOfSomeCalc ()” ha restituito un “int?”, Allora funzionerebbe . C # ha bisogno di capire il tipo indipendentemente da ciò che è a sinistra del compito. Quindi stai dicendo che restituirai un nullo o un int – e la logica nel compilatore non esiste per farlo sostituire un Nullable come un comune denominatore.

Si noti che queste varianti funzionano e possono aiutare a capire:

 object someValue = true ? new Nullable(ResultOfSomeCalc()) : null; object someValue = true ? (int?)ResultOfSomeCalc() : null; 

Spero che questo ti aiuti.

Sembra proprio che questo sia qualcosa che il compilatore dovrebbe essere in grado di capire da solo, ma c’è un altro modo per farlo, usando la parola chiave predefinita. Potrebbe essere il più piccolo meno brutto del cast:

 int? someValue = SomeCondition ? ResultofSomeCalc() : default(int?); 

Questo uso di default non sembra essere ben documentato, ma funziona. Almeno ti impedisce di dover sparpagliare il tuo codice con valori magici (io sostengo che null / zero / false / etc sono davvero valori magici).

Vedi anche Perché questo codice non è valido in C #?

Se la funzione ResultofSomeCalc () restituisce int? allora funzionerà.

Se la tua funzione restituisce int, allora il compilatore emette l’avviso: il tipo di espressione condizionale non può essere determinato perché non esiste una conversione implicita tra “int” e “”
Immagino che sia quello che stai vedendo. Entrambe le espressioni nell’operatore condizionale “?:” Devono avere lo stesso tipo o devono essere convertibili nello stesso tipo tramite un cast implicito.

Modificare il tipo restituito di ResultOfSomeCalc su int ?, oppure sarà necessario disporre del cast sull’espressione null.

Rendi il tuo tipo di funzione ResultOfSomeCalc () come nullabel int come (int?)
int? someValue = (int?) SomeCondition? ResultofSomeCalc (): (int?) Null;