Exercício – Usar parâmetros de tipo de referência e de valor

Concluído

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

  1. No Editor do Visual Studio Code, exclua qualquer código existente dos exercícios anteriores.

  2. 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, b e c são passadas para o método Multiply. 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?

  3. Salve e execute seu código para observar a seguinte saída:

    inside Multiply method: 3 x 4 = 12
    global statement: 3 x 4 = 0
    

    Observe que o valor de c é alterado apenas dentro do método Multiply. Fora do método, c mantém seu valor original.

Teste aprovado por referência

  1. Exclua o código anterior do Editor do Visual Studio Code.

  2. 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 array inicializado para conter alguns valores inteiros. Os valores são exibidos usando o PrintArray método. O Clear mé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?

  3. Salve e execute seu código para observar a seguinte saída:

    1 2 3 4 5 
    0 0 0 0 0
    

    Observe que a matriz permanece alterada fora do escopo do Clear método. Isso acontece porque o Clear mé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.

  1. No Editor do Visual Studio Code, exclua qualquer código existente dos exercícios anteriores.

  2. 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}");
    }
    
  3. Salve e execute seu código para observar a seguinte saída:

    Start: Healthy
    Middle: Unhealthy
    End: Healthy
    

    Se o SetHealth mé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 SetHealth para usar a variável de status global.

  4. 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 status com o novo valor de cadeia de caracteres.

  5. Salve e execute seu código para observar a seguinte saída:

    Start: Healthy
    Middle: Unhealthy
    End: Unhealthy
    

    Agora, 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.