7
votes

Comment Runtime connaît le type exact d'une valeur de valeur en boîte?

Je comprends quelle est la boxe. Un type de valeur est en boîte sur un type objet / référence et est ensuite stocké sur le tas géré comme objet. Mais je ne peux pas obtenir à travers une boîte de dérivation.

Unboxing convertit votre type / type de référence à la valeur Type de valeur P>

int i = 123;
long lng = i;


5 commentaires

Qu'en est-il de la boîte.getType ()?


Le temps d'exécution connaît le type de chaque objet . Les valeurs en boîte ne sont pas différentes.


Supposons que vous ayez un ball qui est de type de valeur, vous mettez une balle dans la vitre . Cela vous empêche-t-il de savoir que c'est une balle dans une boîte de verre? Vous pouvez clairement voir que ce n'est pas ça? Juste comme ça..


C'est une question légèrement déroutante. Imaginez que vous ayez créé une instance FOO (type de référence), puis attribuée à une variable objet . Ne vous attendez-vous pas également à la même exception si vous essayez de la jeter dans une instance bar (aussi un type de référence)? Comme @jonathonreinhart, dit, la boxe / un booxing ne vient pas vraiment de la sorte.


@Danielkelleley, j'admets que je n'ai pas mentionné sur ma confusion, que lorsque la boxe / un incorporation entre en jeu, même la conversion d'un type implicitement convertible ne fonctionne pas. Voir mon édition.


4 Réponses :


1
votes

Chaque objet de référence a un tas de métadonnées associées à celle-ci. Cela inclut le type exact de l'objet donné (c'est pourquoi vous pouvez avoir une sécurité de type du tout).

Alors, tandis que le int est par rapport à la valeur, ces informations sont effectivement manquantes (pas que cela importe), mais une fois que vous l'avez enfoncée, cela crée un nouvel objet avec toutes les métadonnées nécessaires. Cela signifie également que lorsqu'un int est de 4 octets, un coffret int est beaucoup plus que cela - vous avez une référence maintenant (4-8 octets), le valeur elle-même (4) et les métadonnées (qui inclut la poignée de type spécifique). Ceci est très différent de par exemple. C ++, qui vous permet de lancer n'importe quel pointeur à un pointeur de n'importe quel type (et de vous laisser gérer les erreurs lorsque vous le faites mal).

Encore une fois, tous les objets de référence ont cette métadonnée. C'est une partie importante du coût des types de référence, mais c'est aussi le moyen par lequel vous pouvez être sûr de la sécurité de type. Cela montre également joliment à quel point arraylist de int peut vraiment être, et pourquoi int [] ou list est beaucoup plus efficace - n'ignorant même pas les coûts d'allocation (et de collecte plus important) des objets de tas et de la boxe et de la boîteboxing elle-même, le 4 byte int pourrait soudainement 20 octets, juste parce que vous stockez une référence à celle-ci :) < / p>


0 commentaires

4
votes

C'est parce que l'instruction de boxe ajoute le jeton de type de valeur dans l'objet de résultat msdn . Lorsque vous êtes une valeur de déclenchement de l'objet, cette variable est connue de type (et de taille en mémoire). Par conséquent, vous devez lancer un objet au type de valeur d'origine.

Dans votre exemple, vous n'avez même pas besoin de le jeter de Int à long, car c'est un casting implicite.


0 commentaires

11
votes

Lorsqu'une valeur est en boîte, il obtient un en-tête d'objet. Le genre que tout type qui dérive de System.Object a. La valeur suit cet en-tête. L'en-tête contient deux champs, l'un est le "Syncblk", il dispose de diverses utilisations qui dépassent la portée de la question. Le deuxième champ décrit le type d'objet.

C'est celui que vous posez. Il dispose de différents noms dans la littérature, la plus couramment "Poignée de type" ou "Pointeur de la table de la méthode". Ce dernier est la description la plus précise, il s'agit d'un pointeur pour l'info que le CLR tire une trace de chaque fois qu'elle charge un type. Beaucoup de fonctionnalités de cadre dépendent de cela. Objet.gettype () bien sûr. Toute distribution dans votre code ainsi que les sont et comme les opérateurs l'utilisent. Ces moulages sont en sécurité afin que vous ne puissiez pas transformer un chien en chat, la poignée de type fournit cette garantie. Le pointeur de la table de méthode pour votre int points sur la table de méthode pour System.int32

La boxe était très commune dans .net 1.x, avant Les génériques sont devenus disponibles. Tous les types de collecte commune stockés objet au lieu de T. Donc, mettre un élément dans la collecte requise (implicite) boxe, la remédant à nouveau nécessaire à une boîte de consigne explicite avec une distribution.

Pour rendre cela efficace, il était assez important que la gigue n'avait pas besoin de considérer la possibilité qu'une conversion soit requise. Parce que cela nécessite beaucoup plus de travail. Donc, la langue C # incluait la règle selon laquelle une boîte à un autre type est illégale. Tout ce qui est nécessaire maintenant est un chèque sur la poignée de type pour vous assurer qu'il est attendu. La gigue compare directement le pointeur de la table de méthode sur celui de System.int32 dans votre cas. Et la valeur intégrée à l'objet peut être copiée directement sans aucune préoccupation de conversion. Assez vite, aussi vite que possible, cela peut tous être fait avec un code de machine en ligne sans appel CLR.

Cette règle est spécifique à c #, vb.net ne l'a pas. Le compromis typique entre ces deux langues, la concentration de C # est sur la vitesse, vb.net sur la commodité. Conversion d'un autre type Lorsque le non-casage n'est pas un problème, tous les types de valeur simples implémentent iconvertibles. Vous l'écrivez explicite dans votre code, à l'aide de la classe Convert Helper: xxx

qui est assez similaire au code que le compilateur VB.net génère automatiquement.


1 commentaires

Merci pour l'explication précise. Les réponses de Luaan, Paval et Ritesh expliquent également la même chose globale de différentes manières, mais que vous avez frappé la touche sucrée.



2
votes

C'est parce que lorsque vous faites de la boxe au lieu de déplacer la valeur du type de pile sur le tas, elle en crée une copie dans le tas et stocke la référence en pile dans une nouvelle boîte de pile. Donc, votre objet de pile d'origine, c'est-à-dire l'objet de type de valeur avec ses informations de type de données restent dans la pile et maintient son historique. Maintenant au moment de la boîte de réflexion, il compare le type d'objet du tas de type de données d'origine dans la pile et s'il trouve une inadéquation donne l'erreur. Donc, il est nécessaire d'utiliser le même type de données que vous avez en boîte tout en effectuant une boîte de commande.


0 commentaires