Penso que no cerne da sua pergunta está um equívoco sobre os tipos de referência e valor. Provavelmente, isso é algo com o qual todos os desenvolvedores .NET e Java lutaram.
Uma matriz é apenas uma lista de valores. Se for uma matriz de um tipo de referência (digamos a string[]
), a matriz é uma lista de referências a vários string
objetos no heap, pois uma referência é o valor de um tipo de referência. Internamente, essas referências são implementadas como ponteiros para um endereço na memória. Se você deseja visualizar isso, essa matriz seria assim na memória (na pilha):
[ 00000000, 00000000, 00000000, F8AB56AA ]
Essa é uma matriz string
que contém 4 referências a string
objetos no heap (os números aqui são hexadecimais). Atualmente, apenas o último string
realmente aponta para qualquer coisa (a memória é inicializada com todos os zero quando alocada), essa matriz seria basicamente o resultado desse código em C #:
string[] strings = new string[4];
strings[3] = "something"; // the string was allocated at 0xF8AB56AA by the CLR
A matriz acima estaria em um programa de 32 bits. Em um programa de 64 bits, as referências seriam duas vezes maiores ( F8AB56AA
seriam 00000000F8AB56AA
).
Se você possui uma matriz de tipos de valor (digamos um int[]
), a matriz é uma lista de números inteiros, pois o valor de um tipo de valor é o próprio valor (daí o nome). A visualização dessa matriz seria a seguinte:
[ 00000000, 45FF32BB, 00000000, 00000000 ]
Esta é uma matriz de 4 números inteiros, em que apenas o segundo int recebe um valor (para 1174352571, que é a representação decimal desse número hexadecimal) e o restante dos números inteiros seria 0 (como eu disse, a memória é inicializada como zero e 00000000 em hexadecimal é 0 em decimal). O código que produziu essa matriz seria:
int[] integers = new int[4];
integers[1] = 1174352571; // integers[1] = 0x45FF32BB would be valid too
Essa int[]
matriz também seria armazenada na pilha.
Como outro exemplo, a memória de uma short[4]
matriz ficaria assim:
[ 0000, 0000, 0000, 0000 ]
Como o valor de a short
é um número de 2 bytes.
Onde um tipo de valor é armazenado, é apenas um detalhe de implementação, como Eric Lippert explica muito bem aqui , não inerente às diferenças entre os tipos de valor e referência (que é a diferença de comportamento).
Quando você passa algo para um método (seja um tipo de referência ou um tipo de valor), uma cópia do valor do tipo é realmente passada para o método. No caso de um tipo de referência, o valor é uma referência (pense nisso como um ponteiro para uma parte da memória, embora isso também seja um detalhe de implementação) e, no caso de um tipo de valor, o valor é a coisa em si.
// 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){}
O boxe ocorre apenas se você converter um tipo de valor em um tipo de referência. Este código caixas:
object o = 5;