2010-10-13 9 views
9

Ok Devo trascurare qualcosa di estremamente semplice ma sono perso.Confuso da Boxing. La trasmissione da -1 a Int64 genera InvalidCastException

Dato questo

object val = -1; 
var foo = (Int32)(val); 
var bar = (Int64)(val); 

Il cast di Int64 tiri e InvalidCastException.

Riconosco che questo è collegato a qualche stranezza con la boxe ma non capisco il ragionamento.

Da quello che capisco val è inscatolato come Int32 sulla prima riga.

Quindi quando provo a eseguire il cast come qualcosa di diverso da Int32 viene generata InvalidCastException. Suppongo che questo significhi che sto provando a unbox val come Int64 quando è in realtà un Int32?

Ancora sembra strano. Non è possibile che il cast cancelli il valore e quindi provi a eseguire il cast?

Qualcosa di simile (Ovviamente questo è terribilmente semplificato, forse il tipo scatolato non è noto quindi questo non è possibile?):

object val = -1; 
Int32 unboxed = (Int32)(val); 
var bar = (Int64)(unboxed); 

Qualcuno (leggi: Eric Lippert) Scuola me sul ragionamento dietro Questo.

UPDATE: Dal blog di Eric Reed, che ha postato un link a questo è la risposta succinta ero alla ricerca di

" ... Questo sarebbe un enorme quantità di codice per generare, e sarebbe molto lento, il codice è ovviamente così grande che vorresti metterlo nel suo metodo e solo generare una chiamata ad esso, piuttosto che farlo per impostazione predefinita e generare sempre un codice lento, grande e fragile, abbiamo deciso che l'unboxing può solo annullare l'accesso al tipo esatto. Se vuoi chiamare il metodo lento che fa tutto quel goo, è disponibile - puoi sempre chiamare Convert.ToInt32, che fa tutte le analisi in fase di runtime per te. Ti offriamo la scelta tra "veloce e preciso" o "lento e rilassato" e l'impostazione predefinita è la prima. Se si desidera il secondo, chiamare il metodo .... "

+0

questo è qualcosa. estremamente non sim pio. Fa inciampare molte persone ... –

+0

Reed ha ragione; questo viene chiesto più volte a settimana su SO. È stato chiesto due volte ieri. –

+0

Quindi, sono chiaramente zoppo per aver fatto la stessa domanda che tutti gli altri chiedono e non cercano prima. Trovo interessante il fatto che questo abbia ancora 6 voti se è una domanda così comune. Apparentemente il comportamento predefinito non è il comportamento più ovvio. –

risposta

15

Ciò è dovuto al fatto che non è possibile annullare la sincronizzazione e eseguire una conversione in un'unica operazione. È necessario annullare la condivisione del valore Int32 in un Int32, quindi convertire successivamente . il suo tipo

a causa di ciò, questo richiede l'oggetto da unboxed, poi convertito in Int64:

object val = -1; 
int foo = (Int32)val; 
Int64 bar = (Int64)(Int32)val; 

Eric Lippert coperto questo in dettaglio sul suo blog dal titolo Representation and Identity

+0

Awesome, Eric Lippert per proxy :) You rock –

+0

Un altro modo per scrivere: 'Int64 a = -1; oggetto o = a; Int64 b = (Int64) o; 'Grazie Reed! – Nayan

+0

Le persone potrebbero smettere di dire * cast * quando intendono * conversione *? Non esiste un "casting" tra i tipi interi; sono * convertiti *.(È spiacevole che C# usi la stessa sintassi per entrambi.) – Timwi