Em C#, os parâmetros podem ser passador por valor ou por referência. Passando parâmetros por referência permite que o método altere o valor do parâmetro passado e as mudanças persistem após a passagem do método.
Passando uma variavel do tipo Valor para um método significa passar uma cópia da variável para o método. Quaisquer alterações ao parâmetro que ocorrem no interior do método não tem nenhum efeito sobre os dados originais armazenadas na variável. Se você quiser que o chamado método para alterar o valor do parâmetro, você tem que passá-la por referência, usando a palavra ref.
Passagem de parâmetro tipo Valor, por Valor:
// PassingParams1.cs
using System;
class PassingValByVal
{
static void SquareIt(int x)
// O parametro x é chamado por Valor.
// Alterações no x não afetarão o valor original do myInt.
{
x *= x;
Console.WriteLine("O valor antes de chamar o método: {0}", x);
}
public static void Main()
{
int myInt = 5;
Console.WriteLine("O valor antes de chamar o método: {0}",
myInt);
SquareIt(myInt); // Passing myInt by value.
Console.WriteLine("O valor após chamar o método: {0}",
myInt);
}
}
Saida:
O valor antes de chamar o método: 5
O valor dentro do método: 25
O valor após chamar o método: 5
Explicação: A variável
myInt sendo um tipo de valor contém seus dados (o valor 5). Quando SquareIt é chamado, o conteúdo do
myInt é copiado para o parâmetro
x que é multiplicado por ele mesmo dentro do método. No Main porém, o valor de
myInt é o mesmo, antes e depois de chamar o método SquareIt. Logo, a mudança que ocorre no interior do método afeta somente a variável local
x.
Passagem de parâmetro tipo Valor, por Referencia:
// PassingParams2.cs
using System;
class PassingValByRef
{
static void SquareIt(ref int x)
// O parametro x é passado por referencia.
// Alterações no x afetarão a conteudo do myInt.
{
x *= x;
Console.WriteLine("O valor dentro do método: {0}", x);
}
public static void Main()
{
int myInt = 5;
Console.WriteLine("valor antes de chamar o método: {0}",
myInt);
SquareIt(ref myInt); // Passing myInt by reference.
Console.WriteLine("O valor após chamar o método: {0}",
myInt);
}
}
Saida:
O valor antes de chamar o método: 5
O valor dentro do método: 25
O valor após chamar o método: 25
Neste exemplo, não é o conteudo de
myInt que é passado, mas sim, uma referência à
myInt. O parâmetro
x não é um int, mas sim uma referência a um int (neste caso, uma referência à myInt). Portanto, quando
x é multiplicado por ele mesmo dentro do método, o que realmente é multiplicado é o conteudo da variavel refenciada por
x, no caso,
myInt.
Passando de parâmetros do tipo Referência, por Valor:
// PassingParams4.cs
// Passing an array to a method without the ref keyword.
using System;
class PassingRefByVal
{
static void Change(int[] arr)
{
arr[0]=888; // Essa alteraçao ocorre na variavel original.
arr = new int[5] {-3, -1, -2, -3, -4}; // Alteração somente local.
Console.WriteLine("Dentro do método, o primeiro elemento é: {0}", arr[0]);
}
public static void Main()
{
int[] myArray = {1,4,5};
Console.WriteLine("Dentro do Main, antes de chamr o método, o primeiro elemento é: {0}", myArray [0]);
Change(myArray);
Console.WriteLine("Dentro do Main, depois de chamr o método, o primeiro elemento é: {0}", myArray [0]);
}
}
Saida:
Dentro do Main, antes de chamr o método, o primeiro elemento é: 1
Dentro do método, o primeiro elemento é: -3
Dentro do Main, depois de chamr o método, o primeiro elemento é: 888
No exemplo anterior, a matriz,
myArray que é um tipo Referência, ela é passada para o método sem o parâmetro
ref. Nesse caso, uma cópia da referência, o que aponta para
myArray é passada para o método. O resultado mostra que é possível que o método para alterar o conteúdo de um elemento matriz (de 1 a 888). No entanto, alocando uma nova parte de memória usando o operador
new no interior do método Change faz com que a variável
arr referência uma nova matriz. Assim, quaisquer alterações depois disso que não irá afetar a matriz original,
myArray ,que foi criada no interior Main. Na verdade, duas matrizes são criadas neste exemplo, dentro do Main e uma no interior do método Change.
Passando de parâmetros do tipo Referência, por Referencia:
// PassingParams5.cs
// Passando um array para um método utilizando ref.
// Compare com o exemplo anterior.
using System;
class PassingRefByRef
{
static void Change(ref int[] arr)
{
// As duas operaçoes alterarão o a variavel original.
arr[0]=888;
arr = new int[5] {-3, -1, -2, -3, -4};
Console.WriteLine("Dentro do método, o primeiro elemento é: {0}", arr[0]);
}
public static void Main()
{
int[] myArray = {1,4,5};
Console.WriteLine("Dentro principal, antes de chamar o método, o primeiro elemento é o seguinte: {0}", myArray [0]);
Change(ref myArray);
Console.WriteLine("Dentro principal, depois de chamar o método, o primeiro elemento é: {0}", myArray [0]);
}
}
Saida:
Dentro principal, antes de chamar o método, o primeiro elemento é o seguinte: 1
Dentro do método, o primeiro elemento é: -3
Dentro principal, depois de chamar o método, o primeiro elemento é: -3
Todas as mudanças que ocorrem no interior do método afeta a variavel original. De fato, o array original é reatribuídos usando o operador
new. Assim, depois de chamar o método Change, qualquer referência a um dos ponto do
myArray persistirá o valor alterado no método.
Mais informações:
http://msdn.microsoft.com/en-us/library/0f66670z(vs.71).aspx
http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx
http://msdn.microsoft.com/en-us/library/490f96s2.aspxCréditos:
Rodrigo Araujo, Márcio Martins, eu.