Digitare il risultato con l’operatore condizionale in C #

Sto cercando di usare l’operatore condizionale, ma mi sto bloccando sul tipo che pensa debba essere il risultato.

Di seguito è un esempio che ho escogitato per mostrare il problema che sto avendo:

class Program { public static void OutputDateTime(DateTime? datetime) { Console.WriteLine(datetime); } public static bool IsDateTimeHappy(DateTime datetime) { if (DateTime.Compare(datetime, DateTime.Parse("1/1")) == 0) return true; return false; } static void Main(string[] args) { DateTime myDateTime = DateTime.Now; OutputDateTime(IsDateTimeHappy(myDateTime) ? null : myDateTime); Console.ReadLine(); ^ } | } | // This line has the compile issue ---------------+ 

Sulla linea sopra indicata, ottengo il seguente errore di compilazione:

Il tipo di espressione condizionale non può essere determinato perché non esiste una conversione implicita tra “” e “System.DateTime”

Sono confuso perché il parametro è di tipo nullable (DateTime?). Perché ha bisogno di convertire affatto? Se è nullo, usalo, se è un orario, usa quello.

Ho avuto l’impressione che:

 condition ? first_expression : second_expression; 

era lo stesso di:

 if (condition) first_expression; else second_expression; 

Chiaramente questo non è il caso. Qual è il ragionamento dietro a questo?

(NOTA: So che se faccio “myDateTime” un valore DateTime nullable allora funzionerà, ma perché ne ha bisogno?

Come ho affermato prima, questo è un esempio forzato. Nel mio esempio reale “myDateTime” è un valore mappato ai dati che non può essere reso nullable.)

Il compilatore non deduce il tipo di risultato dell’operatore condizionale dall’uso del risultato, ma dai tipi dei suoi argomenti. Il compilatore non riesce quando vede questa espressione perché non può dedurre il tipo del risultato:

 IsDateTimeHappy(myDateTime) ? null : myDateTime; 

Poiché null e DateTime non sono compatibili, è necessario indicare al compilatore quale dovrebbe essere il tipo. Un cast dovrebbe fare il trucco:

 DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime; OutputDateTime(x); 

Ora il compilatore non avrà problemi. Puoi anche scrivere quanto sopra su una riga se preferisci (ma probabilmente non lo farei):

 OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime); 

Eric Lippert ha una buona risposta che è anche rilevante qui e va in maggiori dettagli su come il compilatore determina i tipi.

Il motivo è che l’operatore ternario si aspetta che entrambi gli operandi siano dello stesso tipo. L’intero operatore viene elaborato PRIMA che venga assegnato a un risultato (in questo caso passato in una funzione), quindi il compilatore non può sapere quale sia il tipo di risultato.

 IsDateTimeHappy(myDateTime) ? null : myDateTime 

Nel caso precedente non esiste alcun percorso di conversione tra null e DateTime . Non appena ne lanci uno a DateTime? , il compilatore può convertire l’altro:

 IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime //OR IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime 

La prima riga di codice sopra funziona perché il compilatore può convertire DateTime in DateTime? tramite un operatore di conversione implicito:

 //In Nullable public static implicit operator T?(T value); 

La seconda linea funziona perché null può essere assegnato a DateTime? poiché quest’ultimo è un tipo di riferimento.

La conversione implicita non è consentita dall’istruzione return. Se tu avessi

 if (condition) return first_expression; else return second_expression; 

Quindi dovresti confrontare le mele con le mele. E non avresti problemi – come hai affermato.

Nel tuo caso, ti viene assegnato così tanto spazio nello stack per un DateTime, che è un tipo di valore non annullabile. Quindi stai facendo una dichiarazione che non ha alcun senso per il compilatore. Se dici, ti passerò una A o una B , quindi A e B devono essere la stessa cosa. Nel tuo caso, la B non può mai essere una A

Penso che anche qui ci sia una risposta: i tipi Nullable e l’operatore ternario: perché è `? 10: null` vietato?

Spero che sia ciò di cui avevi bisogno. =]

Quello che dice il compilatore è:

Se IsDateTimeHappy(myDateTime) è false , è necessario restituire un valore di tipo DateTime uguale a myDateTime . Se è true , allora ho bisogno di restituire un valore uguale a null , ma non mi hai detto che tipo dovrebbe essere!

Ecco perché la risposta di Mark è la soluzione. Dopo aver fornito un cast che comunica al compilatore quale tipo di valore verrà restituito se la condizione è true , può controllare se i valori di ritorno true e false possono essere convertiti (o sono) dello stesso tipo.

Cheers Mark! 😉

Anziché utilizzare l’ default(DateTime?) null default(DateTime?) E quindi entrambi i lati del ternario avranno tipi compatibili.