Maison >développement back-end >Tutoriel C#.Net >Exemple de tutoriel sur l'emballage et le déballage

Exemple de tutoriel sur l'emballage et le déballage

零下一度
零下一度original
2017-06-23 15:13:061627parcourir
Boxe :
Les types valeur sont "plus légers" que les types référence dans le sens où ils ne sont pas alloués en tant qu'objets dans le tas géré, ne sont pas récupérés et ne sont pas référencés via des pointeurs. Mais il est souvent nécessaire d'obtenir une référence à un type valeur. Par exemple, supposons que vous souhaitiez créer un objet ArrayList pour contenir un ensemble de structures de points. Le code est le suivant :
programme de classe public scellé.
{
public static void Main()
{
ArrayList a = new ArrayList();
Point p / /Allouer un point (non alloué dans le tas)
pour (int i = 0; i < 10; i++)
{
p.x = p.y = i; //Initialisez les membres dans le type de valeur
a.Add(p); //Encadrez le type de valeur et ajoutez la référence à ArrayList
}
}
}
Chaque itération de boucle initialise un champ de type valeur ponit et stocke le point dans une ArrayList. Mais pensez à ce qui est exactement stocké dans ArrayList ? S'agit-il d'une structure Point, de l'adresse d'une structure Point ou de tout autre chose ? Pour connaître la bonne réponse, vous devez étudier la méthode Add de ArrayList pour comprendre sous quel type ses paramètres sont définis. Le prototype de la méthode Add dans cet exemple est le suivant :
public virtual int Add (Object value);
On voit que Add obtient un paramètre Object, c'est-à-dire, Add obtient l'objet sur le tas géré. Une référence à un objet en tant que paramètre. Mais le code précédent a transmis p, qui est un Point, qui est un type valeur. Pour que le code fonctionne correctement, le type de valeur Point doit être converti en un objet réel hébergé sur le tas et une référence à l'objet doit être obtenue.
Convertissez les types de valeur en types de référence à l'aide du mécanisme de boxe. Voici ce qui se passe lorsque vous encadrez une instance d'un type valeur :
1. Allouez de la mémoire dans le tas géré. La quantité de mémoire allouée est la quantité de mémoire requise pour chaque champ du type valeur, plus la quantité de mémoire requise pour les deux membres supplémentaires (le pointeur d'objet de type et l'index de bloc synchronisé) dont disposent tous les objets du tas géré
2. Le champ de type de valeur est copié dans la mémoire tas nouvellement allouée
3 et l'adresse de l'objet est renvoyée. Désormais, l'objet est une référence d'objet ; le type valeur devient un type référence
Le compilateur C# détecte que le code ci-dessus transmet un type valeur à une méthode qui nécessite un type référence, il génère donc automatiquement du code dans la boîte. l'objet. Ainsi, au moment de l'exécution, les champs actuellement présents dans l'instance de type de valeur Point p sont copiés dans l'objet Point nouvellement alloué. L'adresse de l'objet Point encadré (maintenant un type référence) est renvoyée et transmise à la méthode Add. Les objets ponctuels restent dans le tas jusqu'à ce qu'ils soient récupérés. La variable de type valeur ponctuelle p peut être réutilisée car ArrayList n'en sait rien. Dans ce cas, la durée de vie du type boxed dépasse la durée de vie du type valeur boxed.
Unboxing :
Supposons que vous souhaitiez utiliser le code suivant pour obtenir le premier élément de ArrayList :
Point p=(Point)a[ 0] ;
Il obtient la référence contenue dans l'élément 0 de l'ArrayList, et la vue la place dans l'instance p du type de valeur Point. Pour ce faire, tous les champs de l'objet Point encadré doivent être copiés dans des variables de type valeur, qui se trouvent sur la pile de threads. Le CLR termine la copie en deux étapes. La première étape consiste à obtenir l’adresse de chaque champ Point dans l’objet Point encadré. Ce processus est appelé unboxing. La deuxième partie copie la valeur contenue dans le champ du tas vers l'instance de type valeur basée sur la pile
Le déballage n'inverse pas directement le processus de boxe. Le déballage est un code bien inférieur à la boxe. Le déballage est essentiellement le processus d'obtention d'un pointeur vers un type de valeur primitif contenu dans un objet. En fait, le pointeur pointe vers la partie non boxée de l’instance boxée. Par conséquent, contrairement à la boxe, Chaxiang ne nécessite la copie d'aucun octet en mémoire. Après avoir connu cette différence importante, un autre point important à savoir est qu'elle est souvent suivie d'une copie de champ.
Lorsqu'une instance de type valeur encadrée est déballée, les événements suivants se produisent en interne :
1 Si la variable contenant "une référence au type de valeur encadrée" est nulle, lancez NullReferenceException
.
2, si l'objet référencé n'est pas une instance encadrée du type de valeur requis, lancez InvalidCastException
Le second signifie le travail du code La méthode peut être différente de ce que vous pensez :
public static void Main()
{
Int32 x = 5;
Object o = x //Box x, o fait référence à l'objet boxé
Int16 y = (Int16)o; //Throws InvalidCastException
>
Logiquement parlant, il est tout à fait possible d'obtenir le boxed Int32 référencé par o et forcez sa conversion en int16. Cependant, lors du déballage de l'objet, il ne peut être converti qu'en type de valeur non boxé d'origine - Int32 dans ce cas. Voici la façon correcte de l'écrire :
. public static void Main()
{
Int32 x = 5;
Object o = x; //boxing x, o la référence a été un objet Boxed
Int16 y = (Int16)(Int32)o; //Déballez-le d'abord dans le type correct, puis transformez-le
}
En regardant le code suivant :
public static void Main()
{
Point p;
p.x = p.y = 1;
Object o = p //Box p; , o fait référence à l'instance encadrée
//Changer le champ x de Point en 2
p = (Point)o; //Déballez o et copiez les champs de l'instance en boîte vers la variable de pile
p.x = 2; //Changez l'état de la variable de pile
o = p; //Box p, o fait référence à la nouvelle instance encadrée
>
Le seul but des trois dernières lignes de code est de changer le champ x de Point de 1 Devient 2. Pour ce faire, effectuez d'abord un unboxing, puis effectuez une copie de champ, puis modifiez le champ (sur la pile), et enfin effectuez un boxing (créez une toute nouvelle instance en boîte sur le tas géré). Cela montre l’impact du boxing et du unboxing sur les performances des applications.
Demandez :
public static void Main()
{
Int32 v = 5;
Object o = v;
v = 123;
Console.WriteLine(v+","+(Int32)o);
}
Combien de fois le code ci-dessus a-t-il se produire?

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn