Exercício - Use parâmetros de valor e tipo de referência
Em C#, as variáveis podem ser categorizadas em dois tipos principais, tipos de valor e tipos de referência. Esses tipos descrevem como as variáveis armazenam seus valores.
Tipos de valor como int, bool, float, double, e char contêm diretamente valores. Tipos de referência como string, arraye objetos (como instâncias de Random) não armazenam seus valores diretamente. Em vez disso, os tipos de referência armazenam um endereço onde seu valor está sendo armazenado.
Parâmetros passados por valor e passados por referência
Quando um argumento é passado para um método, as variáveis de tipo de valor têm seus valores copiados para o método. Cada variável tem sua própria cópia do valor, portanto, a variável original não é modificada.
Com tipos de referência, o endereço do valor é passado para o método. A variável dada ao método faz referência ao valor nesse endereço, de modo que as operações nessa variável afetam o valor que é referenciado pelo outro.
Observação
É importante lembrar que string é um tipo de referência, mas é imutável. Isso significa que, uma vez atribuído um valor, ele não pode ser alterado. Em C#, quando métodos e operadores são usados para modificar uma cadeia de caracteres, o resultado que é retornado é, na verdade, um novo objeto de cadeia de caracteres.
Neste exercício, você aprenderá mais sobre como passar argumentos de tipo de referência e valor para métodos.
Teste de passagem por valor
No Editor de Códigos do Visual Studio, exclua qualquer código existente dos exercícios anteriores.
Insira o seguinte código no Editor de Códigos do Visual Studio:
int a = 3; int b = 4; int c = 0; Multiply(a, b, c); Console.WriteLine($"global statement: {a} x {b} = {c}"); void Multiply(int a, int b, int c) { c = a * b; Console.WriteLine($"inside Multiply method: {a} x {b} = {c}"); }As variáveis
a,becsão passadas para oMultiplymétodo. Os valores das variáveis são impressos durante a execução do método e impressos novamente após a conclusão do método.Inteiros são tipos de valor, que têm seus valores copiados quando passados para métodos. O que pensa que será o resultado de
c?Salve e execute seu código para observar a seguinte saída:
inside Multiply method: 3 x 4 = 12 global statement: 3 x 4 = 0Observe que o valor de
csó é alterado dentro doMultiplymétodo. Fora do método,cmantém seu valor original.
Aprovação no teste por referência
Exclua o código anterior do Editor de Códigos do Visual Studio.
Insira o seguinte código no Editor de Códigos do Visual Studio:
int[] array = {1, 2, 3, 4, 5}; PrintArray(array); Clear(array); PrintArray(array); void PrintArray(int[] array) { foreach (int a in array) { Console.Write($"{a} "); } Console.WriteLine(); } void Clear(int[] array) { for (int i = 0; i < array.Length; i++) { array[i] = 0; } }O código começa com
arrayinicializado para conter alguns valores inteiros. Os valores são exibidos usando oPrintArraymétodo. OClearmétodo é chamado na matriz e, em seguida, a matriz é impressa novamente.As matrizes são tipos de referência. Os tipos de referência armazenam o endereço de seus valores na memória. Qual você acha que será o resultado?
Salve e execute seu código para observar a seguinte saída:
1 2 3 4 5 0 0 0 0 0Repare que a matriz continua alterada fora do escopo do método
Clear. Isso acontece porque oClearmétodo atualizou os valores armazenados em cada endereço.
Teste com cadeias de caracteres
Anteriormente, você aprendeu que as cadeias de caracteres são um tipo imutável . Embora uma string seja um tipo de referência, o seu valor não pode ser alterado depois de atribuída, ao contrário de um array. Você deve ter notado isso se tiver usado métodos como string.Replace ou string.ToUpper. Nesta tarefa, você aprenderá a corrigir um erro comum encontrado ao trabalhar com cadeias de caracteres.
No Editor de Códigos do Visual Studio, exclua qualquer código existente dos exercícios anteriores.
Insira o seguinte código no Editor de Códigos do Visual Studio:
string status = "Healthy"; Console.WriteLine($"Start: {status}"); SetHealth(status, false); Console.WriteLine($"End: {status}"); void SetHealth(string status, bool isHealthy) { status = (isHealthy ? "Healthy" : "Unhealthy"); Console.WriteLine($"Middle: {status}"); }Salve e execute seu código para observar a seguinte saída:
Start: Healthy Middle: Unhealthy End: HealthySe o
SetHealthmétodo não gerou o status, você pode ter assumido que o método não foi executado corretamente. Em vez disso, uma nova string com o valor "Unhealthy" foi criada e, em seguida, perdida no escopo do método.Para corrigir esse problema, você pode alterar
SetHealthpara usar a variável de status global em vez disso.Atualize o seu código da seguinte forma:
string status = "Healthy"; Console.WriteLine($"Start: {status}"); SetHealth(false); Console.WriteLine($"End: {status}"); void SetHealth(bool isHealthy) { status = (isHealthy ? "Healthy" : "Unhealthy"); Console.WriteLine($"Middle: {status}"); }Neste código, você substitui a variável global
statuscom o novo valor de cadeia de caracteres.Salve e execute seu código para observar a seguinte saída:
Start: Healthy Middle: Unhealthy End: UnhealthyAgora, a cadeia de caracteres atualizada é capturada e armazenada corretamente.
Recapitulação
Aqui está o que você aprendeu sobre o tipo de valor e os parâmetros de tipo de referência até agora:
- As variáveis podem ser categorizadas como tipos de valor e tipos de referência.
- Os tipos de valor contêm diretamente valores e os tipos de referência armazenam o endereço do valor.
- Os métodos que usam argumentos de tipo de valor criam sua própria cópia dos valores.
- Os métodos que executam alterações em um parâmetro de matriz afetam a matriz de entrada original.
- String é um tipo de referência imutável.
- Os métodos que executam alterações em um parâmetro de cadeia de caracteres não afetam a cadeia de caracteres original.