Problema di tipo Nullable con?: Operatore condizionale


154

Qualcuno potrebbe spiegare perché questo funziona in C # .NET 2.0:

    Nullable<DateTime> foo;
    if (true)
        foo = null;
    else
        foo = new DateTime(0);

... ma questo non:

    Nullable<DateTime> foo;
    foo = true ? null : new DateTime(0);

Quest'ultimo modulo mi dà un errore di compilazione "Il tipo di espressione condizionale non può essere determinato perché non esiste una conversione implicita tra '<null>' e 'System.DateTime'."

Non che non riesca a usare il primo, ma il secondo stile è più coerente con il resto del mio codice.


12
Puoi risparmiare un sacco di digitando usando DateTime? anziché Nullable <DateTime>.
Stewart Johnson,

Risposte:


325

Questa domanda è già stata posta molte volte. Il compilatore ti sta dicendo che non sa come convertire nullin a DateTime.

La soluzione è semplice:

DateTime? foo;
foo = true ? (DateTime?)null : new DateTime(0);

Si noti che Nullable<DateTime>può essere scritto DateTime?che ti farà risparmiare un sacco di digitare.


Funziona abbastanza bene, ma ora non è possibile verificare null foo - avrà sempre un valore. In nessun modo però - come dice MojoFilter "È perché in un operatore ternario, i due valori devono essere dello stesso tipo".
DilbertDave,

@DilbertDave Le informazioni dal post di MojoFilter non sono corrette.
Mishax,

4
Aggiungerei che il compilatore tenta di indovinare il tipo risultante dell'operazione ternaria non osservando la variabile a cui è assegnato, ma osservando invece gli operandi. Trova <null>e, DateTimeinvece di trovare il tipo di antenato comune, cerca solo di trovare una conversione tra loro. (Bit extra: C # riconosce un <null>tipo, ovvero il tipo di ogni nullespressione.)
IllidanS4 vuole Monica indietro il

Se è già stato chiesto un sacco di volte, dov'è la bandiera della domanda duplicata?
starmandeluxe,

@starmandeluxe probabilmente indicano tutti qui (almeno che io come sono arrivato qui)
Scott Chamberlain,

19

Cordiali saluti (Offtopic, ma elegante e in relazione ai tipi nullable) abbiamo un operatore pratico solo per i tipi nullable chiamato l'operatore null coalescing

??

Usato così:

// Left hand is the nullable type, righthand is default if the type is null.
Nullable<DateTime> foo;
DateTime value = foo ?? new DateTime(0);

9
In che modo questo risponde alla sua domanda ??
Stewart Johnson,

3
Nick sta cercando di assegnare null a foo se una condizione è vera. La nullità assegnerà DateTime (0) al valore se foo è null. I due sono completamente indipendenti.
Jeromy Irvine,

4
Da qui la FYI, offtopica ma una cosa carina da sapere.
FlySwat,

Ah ok. È abbastanza utile saperlo.
Jeromy Irvine,

8

È perché in un operatore ternario, i due valori devono essere risolti nello stesso tipo.


10
No, non devono essere dello stesso tipo. O il secondo operando deve essere implicitamente convertibile nel tipo di terzo operando o viceversa.
Mishax,

3

So che questa domanda è stata posta nel 2008 ed è ora 5 anni dopo, ma la risposta contrassegnata come risposta non mi soddisfa. La vera risposta è che DateTime è una struttura e come struttura non è compatibile con null. Hai due modi per risolverlo:

Il primo è rendere null compatibile con DateTime (ad esempio, lanciare null su DateTime? Come suggerisce il gentiluomo con 70 voti positivi, oppure lanciare null su Object o su ValueType).

Il secondo è rendere DateTime compatibile con null (ad esempio, lanciare DateTime su DateTime?).


3

Un'altra soluzione simile a quella accettata è l'uso della defaultparola chiave di C # . Sebbene definito usando generici, è effettivamente applicabile a qualsiasi tipo.

Esempio di utilizzo applicato alla domanda del PO:

Nullable<DateTime> foo;
foo = true ? default(DateTime) : new DateTime(0);

Esempio di utilizzo con la risposta attualmente accettata:

DateTime? foo;
foo = true ? default(DateTime) : new DateTime(0);

Inoltre, utilizzando default, non è necessario specificare la variabile come nullableper assegnarle un nullvalore. Il compilatore assegnerà automaticamente il valore predefinito del tipo di variabile specifico e non si verificherà alcun errore. Esempio:

DateTime foo;
foo = true ? default(DateTime) : new DateTime(0);

13
Non è vero, default(DateTime)non è nullo, è " 1.1.0001 0:00:00", lo stesso di new DateTime(0).
IllidanS4 vuole che Monica torni il

@ IllidanS4, non ho detto che è uguale a null, solo che usando default()te puoi assegnarlo a un nullablevalore (come afferma MSDN). Gli esempi che dimostrano la versatilità mostro che può essere utilizzato con Nullable<DateTime>, DateTime?e semplicemente DateTime. Se ritieni che ciò non sia corretto, puoi fornire un PoC in cui questi falliscono?
newfurniturey

3
Bene, l'interrogante voleva memorizzare nullnella variabile, no default(DateTime), quindi questo è fuorviante al massimo. Questo non è "versatile" come intendi, poiché l'espressione nel suo insieme ha ancora lo stesso tipo - DateTimee puoi sostituirla default(DateTime)con new DateTime()e farà la stessa cosa. Forse default(DateTime?)è quello che intendevi, dal momento che è effettivamente uguale a null.
IllidanS4 vuole Monica indietro il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.