Passagem de parâmetros (Value, Out, Ref, Params)

Value

Criaremos para cada exemplo um arquivo e compilaremos para ver o resultado.

Value é o tipo de parâmetro default no C#. Se o parâmetro não tiver nenhum modificador, ele é um parâmetro value e uma cópia do valor é passada para o método, o que significa que qualquer mudança no valor do parâmetro é feita localmente no método e não é passada de volta para o código que chamou o método, por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// cria um alias para facilitar o acesso aos membros do System
using System;
 
// Cria a nossa classe de exemplo
class MinhaClasse
{
      public void Metodo(int v1)
      {
            v1 = 100;
            Console.WriteLine("Valor em Metodo = " + v1);
      }
}
 
// classe para execução do aplicativo
class Class1
{
      static void Main()
      {
            // cria uma nova instância da classe MinhaClasse
            MinhaClasse obj = new MinhaClasse();
            int valor = 5;
            obj.Metodo(valor);
            Console.WriteLine("Valor na Main = " + valor);
      }
}

Compile e veja a saída no Console:

Embora o valor do parâmetro v1 tenha sido modificado dentro do método “Metodo”, essa mudança não foi refletida na Main (que chamou o método), considerando que parâmetros por valor passam uma cópia da variável, portanto, são somente de entrada.

Out

Out é um parâmetro de saída. Seu valor somente é passado de uma função. O parâmetro out é criado precedendo o tipo de dado com o modificador out. Sempre que um parâmetro out é passado, somente a referência da variável é passada para a função:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// cria um alias para facilitar o acesso aos membros do System
using System;
 
// Cria a nossa classe de exemplo
class MinhaClasse
{
      public void Metodo(out int v1)
      {
            v1 = 100;
            Console.WriteLine("Valor em Metodo = " + v1);
      }
}
 
// classe para execução do aplicativo
class Class1
{
      static void Main()
      {
            // cria uma nova instância da classe MinhaClasse
            MinhaClasse obj = new MinhaClasse();
            int valor = 5;
            obj.Metodo(out valor);
            Console.WriteLine("Valor na Main = " + valor);
      }
}

Compile e veja a saída no Console:

A saída no exemplo acima no método Main será 100, uma vez que o valor do parâmetro out é passado de volta ao código chamador.

Ref

Parâmetros ref são de entrada e saída, o que significa que podem ser usados tanto para passar um valor para um método, quanto para receber de volta esse valor de uma função. Parâmetros ref são criados precedendo um tipo de dado com o modificador ref. Sempre que um parâmetro ref é passado, é uma referência da variável que é passada para o método.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// cria um alias para facilitar o acesso aos membros do System
using System;
 
// Cria a nossa classe de exemplo
class MinhaClasse
{
      public void Metodo(ref int v1)
      {
            v1 = v1 + 100;
      }
}
 
// classe para execução do aplicativo
class Class1
{
      static void Main()
      {
            // cria uma nova instância da classe MinhaClasse
            MinhaClasse obj = new MinhaClasse();
            int valor = 5;
            obj.Metodo(ref valor);
            Console.WriteLine("Valor na Main = " + valor);
      }
}

Compile e veja a saída no Console:

A saída do exemplo acima será 105, uma vez que o parâmetro ref atua tanto como parâmetro de entrada, como de saída.

Params

O parâmetro params necessita ser um array unidimensional ou um jagged arra. Isso possibilita ter argumentos de tamanho variável:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// cria um alias para facilitar o acesso aos membros do System
using System;
 
// Cria a nossa classe de exemplo
class MinhaClasse
{
      public int Soma(params int[] v1)
      {
            int v2 = 0;
            foreach(int v in v1)
            {
                  v2 = v2 + v;
            }
            return v2;
      }
}
 
// classe para execução do aplicativo
class Class1
{
      static void Main()
      {
            // cria uma nova instância da classe MinhaClasse
            MinhaClasse obj = new MinhaClasse();
            Console.WriteLine(obj.Soma(10, 20, 30));
            Console.WriteLine(obj.Soma(10, 20, 30, 40, 50));  
      }
}

Compile e veja a saída no Console:

O valor passado como um parâmetro params, pode ser uma lista de valores separada por vírgula ou um array unidimensional em que o parâmetro params é somente de entrada.

Note que parâmetros ref e out devem ser informados tanto no protótipo do método como na chamada. Apesar de várias opções, os parâmetros por valor e por referência resolvem a grande maioria dos problemas. É necessária uma atenção especial para tipos passados por parâmetros, pois tipos por referência são sempre passados por referência mesmo que isso não seja especificado.

Passagem de parâmetros e sobrecarga de métodos

A passagem de parâmetros para funções também é feita de maneira simples, por exemplo, o código abaixo implementa a função soma da classe “MinhaClasse” recebendo dois valores para serem somados:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// cria um alias para facilitar o acesso aos membros do System
using System;
 
// Cria a nossa classe de exemplo
class MinhaClasse
{
      int n1 = 2, n2 = 4;
 
      // Função para somar e retonar os valores declarados anteriormente
      public int soma()
      {
            return n1 + n2;
      }
 
      public double soma(double v1, double v2)
      {
            return v1 + v2;
      }
}
 
// classe para execução do aplicativo
class Class1
{
      static void Main()
      {
            // cria uma nova instância da classe MinhaClasse
            MinhaClasse obj = new MinhaClasse();
            // declara uma variável para receber o valor da soma
            // de dois valores passados por parâmetro
            int soma1 = obj.soma();
            double soma2 = obj.soma(5, 5);
            // Coloca os valores na tela
            Console.WriteLine("soma1 = {0} e soma2 = {1}", soma1.ToString(), soma2.ToString());
      }
}

Compile e veja a saída do console:

Repare que utilizamos o recurso de sobrecarga de métodos, pois foi possível implementar outro método de nome “soma” sem precisar alterar a existente. A diferenciação entre métodos usando sobrecarga se dá pela lista de parâmetros.

Sobrecarga de métodos consiste em fazer mais de uma implementação de mesmo nome, mas que são diferenciadas pela sua lista de parâmetros. No exemplo do código da classe “MinhaClasse”, construímos duas funções de mesmo nome com lista de parâmetros diferenciados:

1
2
3
4
5
6
7
8
9
public int soma()
{
      return n1 + n2;
}
 
public double soma(double v1, double v2)
{
      return v1 + v2;
}

A sobrecarga também faz diferenciação de métodos através dos tipos dos parâmetros, mas não do tipo de retorno, por exemplo:

Implementação válida

1
2
3
4
5
6
7
8
9
10
11
...
public int soma(int V1)
{
      ...
}
 
public int soma(double v1)
{
      ...
}
...

Implementação inválida

1
2
3
4
5
6
7
8
9
10
11
...
public int soma(int V1)
{
      ...
}
 
public double soma(int v1)
{
      ...
}
...

O interessante da sobrecarga é que podemos oferecer várias opções de um mesmo método que variam dependendo da necessidade e implementação.

A passagem de parâmetros para método pode ser feita de quatro maneiras:

  • value (por valor)
  • out (saída)
  • ref (por referência)
  • params (multidimensional)