Je pense qu'au cœur de votre question se trouve un malentendu sur les types de référence et de valeur. C'est une question à laquelle tous les développeurs .NET et Java ont dû faire face.
Un tableau est juste une liste de valeurs. S'il s'agit d'un tableau de type référence (disons un string[]
), alors le tableau est une liste de références à diverses string
sur le tas, car une référence est la valeur d'un type de référence. En interne, ces références sont implémentées comme des pointeurs vers une adresse en mémoire. Si vous souhaitez visualiser cela, un tel tableau ressemblerait à ceci en mémoire (sur le tas) :
[ 00000000, 00000000, 00000000, F8AB56AA ]
Il s'agit d'un tableau de string
qui contient 4 références à string
objets sur le tas (les chiffres ici sont hexadécimaux). Actuellement, seul le dernier string
ne pointe en fait sur rien (la mémoire est initialisée à tous les zéros lorsqu'elle est allouée), ce tableau serait en fait le résultat de ce code en C# :
string[] strings = new string[4];
strings[3] = "something"; // the string was allocated at 0xF8AB56AA by the CLR
Le tableau ci-dessus serait dans un programme 32 bits. Dans un programme 64 bits, les références seraient deux fois plus grandes ( F8AB56AA
serait 00000000F8AB56AA
).
Si vous avez un tableau de types de valeurs (disons un int[]
), alors le tableau est une liste d'entiers, comme l'indique l'option valeur d'une catégorie de valeur es la valeur elle-même (d'où le nom). La visualisation d'un tel tableau serait la suivante :
[ 00000000, 45FF32BB, 00000000, 00000000 ]
Il s'agit d'un tableau de 4 entiers, où seul le deuxième int se voit attribuer une valeur (à 1174352571, qui est la représentation décimale de ce nombre hexadécimal) et le reste des entiers serait 0 (comme je l'ai dit, la mémoire est initialisée à zéro et 00000000 en hexadécimal est 0 en décimal). Le code qui produit ce tableau serait :
int[] integers = new int[4];
integers[1] = 1174352571; // integers[1] = 0x45FF32BB would be valid too
Ce site int[]
sera également stocké dans le tas.
Autre exemple, la mémoire d'un short[4]
ressemblerait à ceci :
[ 0000, 0000, 0000, 0000 ]
Comme le valeur d'un short
est un nombre de 2 octets.
L'endroit où un type de valeur est stocké n'est qu'un détail de mise en œuvre, comme l'explique très bien Eric Lippert. aquí Les différences entre les types de valeurs et de références ne sont pas inhérentes aux différences entre les types de valeurs et de références (qui sont des différences de comportement).
Lorsque vous passez quelque chose à une méthode (qu'il s'agisse d'un type de référence ou d'un type de valeur), un message de type copie de la valeur du type est effectivement passé à la méthode. Dans le cas d'un type de référence, le valeur est une référence (pensez-y comme un pointeur vers un élément de la mémoire, bien qu'il s'agisse également d'un détail de mise en œuvre) et dans le cas d'un type de valeur, la valeur est la chose elle-même.
// Calling this method creates a copy of the *reference* to the string
// and a copy of the int itself, so copies of the *values*
void SomeMethod(string s, int i){}
La boxe ne se produit que si vous convertir un type de valeur à un type de référence. Ce code encadre :
object o = 5;