Exercício – Descobrir tipos de referência
- 8 minutos
Os tipos de referência incluem matrizes, classes e cadeias de caracteres. Os tipos de referência são tratados de maneira diferente dos tipos de valor em relação a como os valores são armazenados quando o aplicativo está em execução.
Neste exercício, você aprenderá que tipos de referência são diferentes de tipos de valor e saberá como usar o operador new para associar uma variável a um valor na memória do computador.
Como os tipos de referência são diferentes dos tipos de valor
Uma variável de tipo de valor armazena os próprios valores diretamente em uma área de armazenamento chamada pilha. A pilha é a memória alocada ao código que está em execução, no momento, na CPU (também conhecida como o registro de ativação ou quadro de ativação). Quando a execução do registro de ativação for concluída, os valores na pilha serão removidos.
Uma variável de tipo de referência armazena os próprios valores em uma região de memória separada chamada heap. O heap é uma área de memória compartilhada entre muitos aplicativos em execução no sistema operacional ao mesmo tempo. O Tempo de Execução do .NET comunica-se com o sistema operacional para determinar quais endereços de memória estão disponíveis e solicita um endereço em que ele possa armazenar o valor. O runtime do .NET armazena o valor e, em seguida, retorna o endereço de memória à variável. Quando o código usa a variável, o Tempo de Execução do .NET pesquisa sem interrupção o endereço armazenado na variável e recupera o valor que está armazenado lá.
A seguir, você escreverá um código que ilustra essas ideias com mais clareza.
Definir uma variável de tipo de referência
Exclua ou use o operador de comentário de linha
//para remover todo o código dos exercícios anteriores.Atualize o código no Editor do Visual Studio Code da seguinte maneira:
int[] data;O código anterior define uma variável que pode armazenar um valor da matriz
intde tipo.Nesse momento,
dataé simplesmente uma variável que pode armazenar uma referência ou, em vez disso, um endereço de memória de um valor no heap. Como ela não está apontando para um endereço de memória, é denominada uma referência nula.Criar uma instância da matriz
intusando a palavra-chavenewAtualize o código no Editor do Visual Studio Code para criar e atribuir uma nova instância da matriz
intusando o seguinte código:int[] data; data = new int[3];A palavra-chave
newinforma ao runtime do .NET que ele deve criar uma instância da matrizinte, em seguida, coordenar-se com o sistema operacional para armazená-la na memória. O runtime do .NET cumpre e retorna um endereço de memória da nova matrizint. Finalmente, o endereço de memória é armazenado nos dados de variável. O padrão dos elementos da matrizinté o valor0, pois ele é o valor padrão de umint.Modificar o exemplo de código para executar as duas operações em uma única linha de código
As duas linhas de código na etapa anterior normalmente são encurtadas para uma única linha de código a fim de que ambas declarem a variável e criem uma instância da matriz
int. Modifique o código da etapa 3 para o mostrado a seguir.int[] data = new int[3];Embora não haja uma saída a ser observada, este exercício tem como objetivo esclarecer como a sintaxe C# se relaciona com as etapas do processo de trabalho com tipos de referência.
O que há de diferente no tipo de dados de cadeia de caracteres em C#?
O tipo de dados string também é um tipo de referência. Talvez você esteja se perguntando por que o operador new não foi usado ao declarar uma cadeia de caracteres. Isso é meramente uma conveniência proporcionada pelos designers do C#. Como o tipo de dados string é usado com tanta frequência, é possível usar o seguinte formato:
string shortenedString = "Hello World!";
Console.WriteLine(shortenedString);
Em segundo plano, no entanto, uma instância de System.String é criada e inicializada como "Olá, Mundo!".
Preocupações práticas usando tipos de valor e referência
-
Tipo de valor (int): Neste exemplo,
val_Aeval_Bsão tipos de valor inteiro.
int val_A = 2;
int val_B = val_A;
val_B = 5;
Console.WriteLine("--Value Types--");
Console.WriteLine($"val_A: {val_A}");
Console.WriteLine($"val_B: {val_B}");
Você deve ver o seguinte resultado:
--Value Types--
val_A: 2
val_B: 5
Quando val_B = val_A é executado, o valor de val_A é copiado e armazenado em val_B. Portanto, quando val_B é alterado, val_A permanece inalterado.
-
Tipo de referência (matriz): Neste exemplo,
ref_Aeref_Bsão tipos de referência de matriz.
int[] ref_A= new int[1];
ref_A[0] = 2;
int[] ref_B = ref_A;
ref_B[0] = 5;
Console.WriteLine("--Reference Types--");
Console.WriteLine($"ref_A[0]: {ref_A[0]}");
Console.WriteLine($"ref_B[0]: {ref_B[0]}");
Você deve ver o seguinte resultado:
--Reference Types--
ref_A[0]: 5
ref_B[0]: 5
Quando ref_B = ref_A é executado, ref_B aponta para o mesmo local de memória que ref_A. Portanto, quando ref_B[0] é alterado, ref_A[0] também é alterado porque ambos apontam para o mesmo local de memória. Essa é uma diferença fundamental entre os tipos de valor e os tipos de referência.
Recapitulação
- Os tipos de valor podem armazenar valores menores e são armazenados na pilha. Os tipos de referência podem armazenar grandes valores, e uma nova instância de um tipo de referência é criada usando o operador
new. As variáveis do tipo de referência armazenam uma referência (o endereço de memória) para o valor real armazenado no heap. - Os tipos de referência incluem matrizes, cadeias de caracteres e classes.