2010-10-13 11 views
9

Ok, je dois être sur quelque chose d'extrêmement simple mais je suis perdu.Confus par la boxe. Casting -1 à Int64 throws InvalidCastException

Compte tenu de cette

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

Le casting de Int64 lancers francs et InvalidCastException.

Je reconnais que cela est lié à une certaine étrangeté avec la boxe, mais je ne comprends pas le raisonnement. D'après ce que je comprends val est encadré comme Int32 sur la première ligne.

Ensuite, lorsque j'essaye de lancer comme quelque chose d'autre que Int32 InvalidCastException est levée. Je suppose que cela signifie que j'essaye de déballer Val comme Int64 quand c'est en fait un Int32?

Encore semble étrange. Le casting ne peut-il pas dégrouper la valeur et ensuite essayer d'effectuer la distribution?

Quelque chose comme (Évidemment, cela est horriblement simplificatrice, peut-être le type boxed on ne sait pas si cela est impossible?):

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

Quelqu'un (lire: Eric Lippert) École moi sur le raisonnement derrière ce.

MISE À JOUR: du blog de Eric que Reed a posté un lien vers cette est la réponse succincte je cherchais

» ... Ce serait une énorme quantité de code pour générer, et il serait Le code est bien sûr si grand que vous voudriez le mettre dans sa propre méthode et juste générer un appel à celui-ci.Plutôt que de le faire par défaut, et toujours générer du code qui est lent, grand et fragile, Nous avons décidé que le débobinage ne peut que déballer au type exact Si vous voulez appeler la méthode lente qui fait tout ça, elle est disponible - vous pouvez toujours appeler Convert.ToInt32, qui fait toute cette analyse à l'exécution pour toi. Nous vous donnons le choix entre "rapide et précis" ou "lent et relâché", et le défaut sensible est le premier. Si vous souhaitez que ce dernier appelle la méthode, appelez la méthode .... "

+0

C'est quelque chose. extrêmement non-sim ple. Il voyage beaucoup de monde ... –

+0

Reed a raison; Cela est demandé plusieurs fois par semaine sur SO. Il a été demandé deux fois hier. –

+0

Donc, je suis clairement boiteux pour poser la même question que tout le monde demande et ne cherche pas d'abord. Je trouve intéressant que cela fasse l'objet de 6 votes si c'est une question si commune. Apparemment, le comportement par défaut n'est pas le comportement le plus évident. –

Répondre

15

Ceci est dû au fait que vous ne pouvez pas déballer et effectuer une conversion en une seule opération. Vous devez décompacter la valeur Int32 dans un Int32, puis la convertir . son type

à cause de cela, cela nécessite l'objet à uNBOXED, puis converti en Int64:

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

Eric Lippert a couvert en détail sur son blog intitulé Representation and Identity

+0

Génial, Eric Lippert par un proxy :) Vous basculez –

+0

Une autre façon d'écrire: 'Int64 a = -1; objet o = a; Int64 b = (Int64) o; 'Merci Reed! – Nayan

+0

Les gens peuvent-ils cesser de dire * cast * quand ils veulent dire * conversion *? Il n'y a pas de "casting" entre les types entiers; ils sont * convertis *.(Il est regrettable que C# utilise la même syntaxe pour les deux.) – Timwi