2012-04-08 14 views
25

Al di là la differenza noioso regolare tra Cast e AsC# casting al tipo nullable?

  • se so che mela è un Frutta modo da poter utilizzare (Fruit)apple - e genera un'eccezione se aint
  • as value può essere controllato contro null per vedere se riuscito [non getterà Eccezione ...]

Tuttavia Ive leggere @EricLippert article su questo e c'era un bel campione di circa Nullable valore Tipi:

short? s = (short?)123; 
int? i = s as int?; 

questo non sarà compilazione ...

non in grado di convertire il tipo 'breve? ' a "int?" tramite conversione di riferimento, conversione di boxing, conversione di unboxing, conversione del wrapping o conversione di tipo nullo

Fine.

quindi perché questo:

short? s = (short?)123; 
    int? i = (int?)s; 

Does Compile? (! contro ogni aspettativa ho KNOW che s non è int? - e dovrebbe andare BANG ma aint ...)

Cast verifica qui dovrebbe essere molto più letale di quella precedente esempio (che è andato Bang)

Mi dispiace chiedere di questo argomento molto discusso.

Grazie in anticipo.

+1

hai descritto esattamente ciò che Eric Lippert ha scritto: il cast verrà compilato mentre l'operatore 'as' non lo farà per i casi relativi ai tipi nullable. – Yahia

+0

@Yahia ma siamo d'accordo sul fatto che breve NON è INT? –

+0

short non è int BUT può essere lanciato/convertito in int - e questo è ciò che stai dicendo al compilatore: rendi questo un breve int. – Yahia

risposta

23

Nel primo esempio, l'operatore as tenta di utilizzare l'oggetto s come int?. Poiché int? non si trova in nessuna parte della catena di ereditarietà di short?, questa operazione non riesce.

Nel tuo secondo esempio, stai effettivamente creando un nuovo int? i con il valore da short? s. Questa è un'operazione più generosa, perché non deve conservare l'oggetto originale s sul lato sinistro.

Il punto importante qui è che as non è autorizzato a eseguire operazioni che non preservano l'identità dell'oggetto. Un cast esplicito può.

Ecco cosa dice il C# di serie su come funziona il modulo (int?):

6.1.4 implicita La conversione nullable

predefiniti conversioni implicite che operano sul valore non annullabile tipi possono essere utilizzati anche con forme nullable di questi tipi. Per ciascuna delle il predefinito identità implicita e conversioni numeriche che convertono da un non annullabile tipo di valore S ad un non annullabile tipo di valore T, i seguenti conversioni annullabili implicite esistenti:

· Una conversione implicita da S? a T ?.

· Una conversione implicita da S a T ?.

Valutazione di una conversione implicita annullabile basato sulla conversione sottostante da S a T procede come segue:

· Se la conversione è nullable da S? a T ?:

o Se il valore di origine è null (la proprietà HasValue è false), il risultato è il valore null di tipo T ?.

o In caso contrario, la conversione viene valutata come uno srotolamento da S? a S, seguito dalla conversione sottostante da S a T, seguita da un wrapping (§4.1.10) da T a T ?.

· Se la conversione nullable va da S a T?, La conversione viene valutata come la conversione sottostante da S a T seguita da un wrapping da T a T ?.

+0

oltre a questa spiegazione c'è ancora questa riga '(int?) S' che DO è correlata all'era dell'eredità/boxe .... ma funziona e questa è la cosa che non capisco. –

+0

@RoyiNamir, non capisco davvero. Esiste una conversione da 'short' a' int' (vale a dire in C, Java e praticamente ovunque) e la specifica C# descrive come eseguire la conversione e farlo funzionare su tipi nullable. (Ho aggiunto l'estratto pertinente sopra.) – sblom

+1

@sblom Penso che dovresti 'double-bold 'il paragrafo precedente dicendo' Il punto importante qui è che non è permesso fare nulla che non preservi l'identità dell'oggetto. Un cast esplicito può. - Penso che questo sia il nocciolo del problema. E per quanto riguarda il casting permesso, sono d'accordo, questo è chiaro per me ('as' was not really), e come Eric ha detto che non c'è aritmetica su short-s (non importa a questo ma è più facile da capire, a almeno io, la conversione), converte in int. – NSGaga

3

L'esempio:

int? i = (int?)s; 

Does compilatore perché un cast è che si dice al compilatore che si sa qualcosa che non si può dedurre, cioè, che s può essere convertito in un int?.

Si otterrà l'eccezione solo in fase di esecuzione se il cast non ha esito positivo.

+2

non c'è un'eccezione in fase di esecuzione ..... –

+0

@RoyiNamir - Spiacenti, avrei dovuto aggiungerlo solo nel caso in cui il cast non funzioni. – Oded

0

Penso che sia la causa, in caso di fallimento as vi verrà dato un "valido" null risultato, in modo da falso positivo. Nel secondo caso, il cast è consentito perché, in caso di fallimento, solleverà un'eccezione.

0

Il motivo è int? è solo una abbreviazione di System.Nullable<int> (System.Nullable<T> è il tipo). Il tipo breve definisce un cast esplicito per un int, tuttavia System.Nullable<T> non ha alcun cast esplicito, perché T potrebbe essere qualsiasi altro tipo di valore.