2010-10-12 12 views
7

Ho avuto un problema oggi e non ero del tutto sicuro del motivo per cui non avrebbe funzionato.Tipo di oggetto di inoltro in C#

Il seguente esempio di codice si blocca:

static void Main(string[] args) 
{ 
    int i32 = 10; 
    object obj = i32; 
    long i64 = (long)obj; 
} 

Questo si tradurrà in un InvalidCastException. Perché non funziona? C# non è abbastanza intelligente da sapere che l'oggetto è in realtà di tipo int?

Ho già trovato una soluzione alternativa, ma sono curioso sul motivo per cui l'esempio di codice precedente non ha funzionato in primo luogo.

Grazie, Tim

+1

Ho notato che questo è un duplicato di molte domande precedenti, incluso più recentemente http://stackoverflow.com/questions/3911293 –

risposta

9

Non v'è alcuna fusione disponibile da un Int32 boxed ad un Int64. Fare un cast intermedio int dovrebbe funzionare, perché il compilatore è disposto a generare questo:

// verify obj is a boxed int, unbox it, and perform the *statically* 
// known steps necessary to convert an int to a long 
long i64 = (long) ((int)obj); 

ma non (ipoteticamente) questo:

// Find out what type obj *actually* is at run-time and perform 
// the-known-only-at-run-time steps necessary to produce 
// a long from it, involving *type-specific* IL instructions 
long i64 = (long)obj; 

Ecco un blog post da Eric Lippert su questo.

1

Intendi il compilatore o il runtime?

Il runtime è abbastanza intelligente, quindi genera il InvalidCastException. Il compilatore tuttavia non può sapere con certezza di che tipo è il tuo oggetto, dal momento che hai inscatolato il tuo int.

Boxing e unboxing permettono tipi di valore di essere trattati come oggetti. La boxing di un tipo di valore si trova all'interno di un'istanza del tipo di riferimento Oggetto .

Quindi dal momento che è in box come oggetto, il compilatore non si lamenterà di ciò.

Tutte le informazioni sulla boxe e unboxing qui:

http://msdn.microsoft.com/en-us/library/yz2be5wk%28VS.80%29.aspx

3

Partenza this blog post da Eric Lippert per i dettagli cruenti.

L'essenza di esso è che sarebbe molto lento per il compilatore di capire (per tentativi ed errori, dal momento che object può essere qualsiasi cosa) che tipo è stato inscatolato e se sia o non possono essere lanciati in modo sicuro.