Exercício – Usar parâmetros de tipo de referência e de valor
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, floatdoublee char contêm valores diretamente. 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 fornecida ao método faz referência ao valor nesse endereço, portanto, as operações nessa variável afetam o valor 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 retornado é, na verdade, um novo objeto de cadeia de caracteres.
Neste exercício, você aprenderá mais sobre como passar argumentos de referência e tipo de valor para métodos.
Testar passagem por valor
No Editor do Visual Studio Code, exclua qualquer código existente dos exercícios anteriores.
Insira o seguinte código no Editor do Visual Studio Code:
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 o métodoMultiply. 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 você acha que será a saída 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
cé alterado apenas dentro do métodoMultiply. Fora do método,cmantém seu valor original.
Teste aprovado por referência
Exclua o código anterior do Editor do Visual Studio Code.
Insira o seguinte código no Editor do Visual Studio Code:
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.Matrizes são tipos de referência. Os tipos de referência armazenam o endereço de seus valores na memória. O que 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 0Observe que a matriz permanece alterada fora do escopo do
Clearmétodo. Isso acontece porque oClearmétodo atualizou os valores armazenados em cada endereço.
Testes com cadeias de caracteres
Anteriormente, você aprendeu que as cadeias de caracteres são um tipo imutável . Mesmo que uma cadeia de caracteres seja um tipo de referência, ao contrário de uma matriz, seu valor não pode ser alterado depois de atribuído. Você pode 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 do Visual Studio Code, exclua qualquer código existente dos exercícios anteriores.
Insira o seguinte código no Editor do Visual Studio Code:
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 tiver gerado o status, você pode ter assumido que o método não foi executado corretamente. Em vez disso, uma nova cadeia de caracteres com o valor "Não saudável" 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.Atualize seu código desta maneira:
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}"); }Nesse 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.
Recapitular
Aqui está o que você aprendeu sobre os parâmetros de tipo de valor e 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.
- 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.