Question

Je recherche une réponse claire, concise et précise.

Idéalement comme réponse réelle, bien que les liens vers de bonnes explications soient les bienvenus.

Était-ce utile?

La solution

Les valeurs encadrées sont structures de données qui sont des emballages minimes autour types primitifs*.Les valeurs encadrées sont généralement stockées sous forme de pointeurs vers des objets sur le tas.

Ainsi, les valeurs encadrées utilisent plus de mémoire et nécessitent au minimum deux recherches de mémoire pour y accéder :une fois pour obtenir le pointeur et une autre pour suivre ce pointeur vers la primitive.Ce n’est évidemment pas le genre de chose que vous souhaitez dans vos boucles intérieures.D’un autre côté, les valeurs encadrées fonctionnent généralement mieux avec les autres types du système.Puisqu’il s’agit de structures de données de première classe dans le langage, elles possèdent les métadonnées et la structure attendues des autres structures de données.

En Java et Haskell, les collections génériques ne peuvent pas contenir de valeurs non boxées.Les collections génériques dans .NET peuvent contenir des valeurs non boxées sans pénalités.Là où les génériques de Java ne sont utilisés que pour la vérification du type au moment de la compilation, .NET le fera. générer des classes spécifiques pour chaque type générique instancié au moment de l'exécution.

Java et Haskell ont des tableaux non emballés, mais ils sont nettement moins pratiques que les autres collections.Cependant, lorsque des performances optimales sont nécessaires, cela vaut la peine d'éviter un petit inconvénient pour éviter les frais généraux liés au boxing et au unboxing.

* Pour cette discussion, une valeur primitive est toute valeur pouvant être stockée sur la pile d'appels, plutôt que stocké sous forme de pointeur vers une valeur sur le tas.Il s'agit souvent uniquement des types de machines (ints, floats, etc.), des structures et parfois des tableaux de taille statique..NET-land les appelle types valeur (par opposition aux types référence).Les gens de Java les appellent des types primitifs.Les Haskellions les appellent simplement « non emballés ».

** Je me concentre également sur Java, Haskell et C# dans cette réponse, car c'est ce que je sais.Pour ce que ça vaut, Python, Ruby et Javascript ont tous des valeurs exclusivement encadrées.C'est ce qu'on appelle aussi la démarche « Tout est objet »***.

*** Mise en garde:Un compilateur / JIT suffisamment avancé peut dans certains cas détecter qu'une valeur sémantiquement encadrée lors de l'examen de la source peut être en toute sécurité une valeur non encadrée au moment de l'exécution.Essentiellement, grâce à de brillants implémenteurs de langage, vos boîtes sont parfois gratuites.

Autres conseils

depuis C# 3.0 en bref:

La boxe est l'acte de couler un type de valeur dans un type de référence:

int x = 9; 
object o = x; // boxing the int

le déballage est...l'inverse :

// unboxing o
object o = 9; 
int x = (int)o; 

La boxe et le déballage sont le processus de conversion d'une valeur primitive en une classe wrapper orientée objet (boxing), ou de conversion d'une valeur d'une classe wrapper orientée objet en valeur primitive (unboxing).

Par exemple, en Java, vous devrez peut-être convertir un int valeur dans un Integer (boxe) si vous souhaitez le stocker dans un Collection car les primitives ne peuvent pas être stockées dans un Collection, seulement des objets.Mais quand tu veux le sortir du Collection vous souhaiterez peut-être obtenir la valeur sous forme de int et pas un Integer donc vous le déballeriez.

La mise en boîte et le déballage ne sont pas intrinsèquement mauvais, mais c'est un compromis.Selon l'implémentation du langage, cela peut être plus lent et plus gourmand en mémoire que la simple utilisation de primitives.Cependant, cela peut également vous permettre d'utiliser des structures de données de niveau supérieur et d'obtenir une plus grande flexibilité dans votre code.

De nos jours, on en parle le plus souvent dans le contexte de la fonctionnalité "autoboxing/autounboxing" de Java (et d'autres langages).Voici une explication centrée sur Java de l'autoboxing.

Dans .Net :

Souvent, vous ne pouvez pas compter sur le type de variable qu'une fonction consommera, vous devez donc utiliser une variable objet qui s'étend du plus petit dénominateur commun - dans .Net, c'est object.

Cependant object est une classe et stocke son contenu comme référence.

List<int> notBoxed = new List<int> { 1, 2, 3 };
int i = notBoxed[1]; // this is the actual value

List<object> boxed = new List<object> { 1, 2, 3 };
int j = (int) boxed[1]; // this is an object that can be 'unboxed' to an int

Bien que les deux contiennent les mêmes informations, la deuxième liste est plus grande et plus lente.Chaque valeur de la deuxième liste est en fait une référence à un object qui tient le int.

C'est ce qu'on appelle encadré parce que le int est enveloppé par le object.Quand il est rejeté, le int est déballé - reconverti à sa valeur.

Pour les types valeur (c'est-à-diretous structs), c'est lent et utilise potentiellement beaucoup plus d'espace.

Pour les types de référence (c.-à-d.tous classes), c'est beaucoup moins problématique, car ils sont de toute façon stockés comme référence.

Un autre problème avec un type valeur encadré est qu'il n'est pas évident que vous ayez affaire à la boîte plutôt qu'à la valeur.Quand on compare deux structs alors vous comparez des valeurs, mais lorsque vous comparez deux classes alors (par défaut) vous comparez la référence - c'est-à-direest-ce le même cas ?

Cela peut prêter à confusion lorsqu’il s’agit de types de valeurs encadrées :

int a = 7;
int b = 7;

if(a == b) // Evaluates to true, because a and b have the same value

object c = (object) 7;
object d = (object) 7;

if(c == d) // Evaluates to false, because c and d are different instances

Il est facile de contourner le problème :

if(c.Equals(d)) // Evaluates to true because it calls the underlying int's equals

if(((int) c) == ((int) d)) // Evaluates to true once the values are cast

Cependant, c'est une autre chose à laquelle il faut faire attention lorsqu'il s'agit de valeurs encadrées.

Les collections génériques .NET FCL :

List<T>
Dictionary<TKey, UValue>
SortedDictionary<TKey, UValue>
Stack<T>
Queue<T>
LinkedList<T>

ont tous été conçus pour surmonter les problèmes de performances liés au boxing et au unboxing dans les implémentations précédentes de collections.

Pour en savoir plus, voir le chapitre 16, CLR via C# (2e édition).

La boxe est le processus de conversion d’un type valeur en un type référence.

Le déballage est la conversion d'un type référence en un type valeur.

EX: int i=123;
    object o=i;// Boxing
    int j=(int)o;// UnBoxing

Les types de valeur sont :
int, char et structures, énumérations.Les types de référence sont :Classes, interfaces, tableaux, chaînes et objets

Le boxing et le unboxing facilitent le traitement des types de valeur comme des objets.La boxe signifie convertir une valeur en une instance du type référence d’objet.Par exemple, Int est une classe et int est un type de données.Conversion int à Int est un exemple de boxe, alors que la conversion Int à int est en train de déballer.Le concept aide au garbage collection, Unboxing, en revanche, convertit le type d'objet en type valeur.

int i=123;
object o=(object)i; //Boxing

o=123;
i=(int)o; //Unboxing.

Comme toute autre chose, l’autoboxing peut être problématique s’il n’est pas utilisé avec précaution.Le classique est de se retrouver avec une NullPointerException et de ne pas pouvoir la retrouver.Même avec un débogueur.Essaye ça:

public class TestAutoboxNPE
{
    public static void main(String[] args)
    {
        Integer i = null;

        // .. do some other stuff and forget to initialise i

        i = addOne(i);           // Whoa! NPE!
    }

    public static int addOne(int i)
    {
        return i + 1;
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top