Domanda

Sto provando ad usare l'operatore condizionale, ma io sono sempre appeso al tipo che pensa che il risultato dovrebbe essere.

Di seguito è riportato 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  ---------------+

Nella riga sopra indicato, ottengo il seguente errore di compilazione:

Tipo di un'espressione condizionale non può essere determinato perché non v'è alcuna conversione implicita tra '' e 'System.DateTime'

Sono confuso perché il parametro è un tipo nullable (DateTime?). Perché ha bisogno di convertire a tutti? Se si tratta di nulla quindi utilizzare tale, se si tratta di una data e ora quindi utilizzare tale.

Ho avuto l'impressione che:

condition ? first_expression : second_expression;

era lo stesso:

if (condition)
   first_expression;
else
   second_expression;

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

(NOTA:.? Io so che se faccio "MyDateTime" DateTime nullable allora funzionerà Ma perché lo fa bisogno

Come ho detto prima questo è un esempio inventato. Nel mio vero esempio "MyDateTime" è un dato valore che non può essere fatto annullabile mappati.)

È stato utile?

Soluzione

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

IsDateTimeHappy(myDateTime) ? null : myDateTime;

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

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

Ora il compilatore non avrà problemi. Si può anche scrivere quanto sopra su una sola riga, se si preferisce (ma non sarebbe probabilmente fare questo):

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

Eric Lippert ha una buona risposta che è anche rilevante qui e va in ulteriori dettagli sul modo in cui il compilatore determina i tipi.

Altri suggerimenti

Il motivo è l'operatore ternario aspetta che entrambe gli operandi siano dello stesso tipo. L'intero operatore get elaborata prima che venga assegnato ad un risultato (in questo caso passato in una funzione), in modo che il compilatore non può sapere qual è il tipo di risultato è.

IsDateTimeHappy(myDateTime) ? null : myDateTime

Nel caso di cui sopra non v'è percorso di conversione tra null e DateTime. Non appena si lanci uno di loro a DateTime?, il compilatore in grado di convertire l'altro:

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

La linea di pugno di codice precedente funziona perché il compilatore in grado di convertire DateTime a DateTime? tramite un operatore di conversione implicita:

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

La seconda riga funziona perché null può essere assegnato al DateTime? poiché quest'ultimo è un tipo di riferimento.

La conversione implicita non è consentita dalla dichiarazione di ritorno. Se tu avessi

if (condition)
    return first_expression;
else
    return second_expression;

Poi si sarebbe confrontando le mele alle mele. E che avresti avuto problemi -. Come avete dichiarato

Nel tuo caso, hai assegnato tanto spazio nello stack per un DateTime - che è un tipo di valore non nullable. Così si sta facendo una dichiarazione che non ha alcun senso per il compilatore. Se dici, ho intenzione di passare voi un A o un B, poi il A e la necessità B essere la stessa cosa. Nel tuo caso, il B non può mai essere un A.

Credo che questo sia anche risposto qui: tipi nullable e l'operatore ternario: perché è `? 10:? Null` vietato

La speranza è questo che avete avuto bisogno. =]

Quello che il compilatore sta dicendo è:

  

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

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

Ciao Marco! ; -)

Invece di utilizzo null default(DateTime?) e poi entrambi i lati del ternario avranno tipi compatibili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top