Exercício - Use parâmetros de valor e tipo de referência

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

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

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

  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 só é alterado dentro do Multiply método. Fora do método, c mantém seu valor original.

Aprovação no teste por referência

  1. Exclua o código anterior do Editor de Códigos do Visual Studio.

  2. 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 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.

    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?

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

    1 2 3 4 5 
    0 0 0 0 0
    

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

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

  2. 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}");
    }
    
  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 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 SetHealth para usar a variável de status global em vez disso.

  4. 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 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.

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.