Operatore Null-Coalescing - Perché il casting?
-
27-10-2019 - |
Domanda
Qualcuno può dirmi perché la prima delle seguenti affermazioni genera un errore di compilazione e la seconda no?
NewDatabase.AddInParameter(NewCommand, "@SomeString", DbType.String, SomeString ?? DBNull.Value); // <-- Throws compilation error!
NewDatabase.AddInParameter(NewCommand, "@SomeString", DbType.String, (object)(SomeString) ?? DBNull.Value); // <-- Compiles!
Ho provato altri tipi nullable come byte?
e ho ottenuto lo stesso risultato.Qualcuno può dirmi perché devo prima eseguire il cast sull'oggetto?
Soluzione
Devi dire al compilatore quale tipo usare. Il tipo di risultato dell'operatore di coalescenza null deve essere uguale a uno dei tipi di operando (o il tipo sottostante del primo operando, se è un tipo di valore nullable, in alcuni casi). Non cerca di trovare un "tipo più specifico in cui entrambi gli operandi possono essere convertiti" o qualcosa del genere.
Per i dettagli su come viene definita la lingua quando si tratta dell'operatore di coalescenza nullo, vedere Specifica del linguaggio C # 4 , sezione 7.13:
Il tipo di espressione
a ?? b
dipende da quali conversioni implicite sono disponibili sugli operandi. In ordine di preferenza, il tipo dia ?? b
èA0
,A
oB
, doveA
è il tipo dia
(a condizione che a abbia un tipo),B
è il tipo dib
(purchéb
eA0
) è il tipo sottostante diA
seA
è un tipo nullable o altrimentiA
.
Altri suggerimenti
Il primo esempio non riesce perché SomeString
e DBValue.Null
non sono tipi implicitamente intercambiabili .
Questo perché il tipo sul lato destro dell'operatore di coalescenza nullo deve essere convertibile implicitamente nel tipo sul lato sinistro (o viceversa).Per il tuo primo esempio, i tipi coinvolti sono string
e DBNull
.Questi tipi non sono correlati, quindi la conversione non riesce.
DBValue.Null non è una stringa;è un oggetto..NET non eseguirà il cast implicito a Object nelle espressioni;deve essere detto esplicitamente che ti aspetti un risultato Object.
Perché l'espressione deve avere un unico tipo di ritorno.Poiché String
e DbValue
non possono essere scambiati tra loro, il compilatore non è in grado di capire quale tipo return desideri.Quando esegui il cast su Object, stai dando al compilatore un tipo a cui può eseguire il cast.