- (nenhum): Se um parâmetro não é marcado com um modificador de parâmetro, ele será passado por valor, significando que o método chamado recebe uma cópia do dado original.
- out: Parâmetros out devem ser atribuídos pelo método sendo chamado, e portanto são passados por referência. Se o método chamado não atribuir os parâmetros out, você recebe um erro de compilação.
- ref: O valor é inicialmente atribuído pelo chamador e pode ser opcionalmente reatribuído pelo método chamado (já que os dados também são passados por referência). Nenhum erro de compilação é gerado se o método chamado não atribuir um parâmetro ref.
- params: Este modificador de parâmetro permite a você enviar um número variável de argumentos como um único parâmetro lógico. Um método pode ter somente um modificador params, e ele deve ser o último parâmetro do método. Na verdade, você pode raramente precisar usar o modificador params, mas esteja ciente de que vários métodos dentro das classes da biblioteca base do .NET Framework fazem uso deste recurso da linguagem C#.
Forma Padrão de Passagem de Parâmetros
A forma default pela qual um parâmetro é enviado para uma função é por valor. Basicamente, se você não marcar um parâmetro com um modificador de parâmetro, uma cópia do dado é passada para a função.
Considere que você tenha o seguinte método dentro da classe Program que opera sobre dois tipos de dados numéricos passados por valor:
// Por padrão os argumentos são passados por valor.
static int Somar(int x, int y)
{
int total = x + y;
// O chamador não verá estas mudanças já que você
// está modificando uma cópia dos dados originais.
// O chamador não verá estas mudanças já que você
// está modificando uma cópia dos dados originais.
x = 10000;
y = 88888;
return total;
}
Dados numéricos entram na categoria de tipos de valor. Portanto, se você modificar os valores dos parâmetros dentro do escopo do método essas alterações não serão visíveis para o chamador, pois você está modificando os valores de uma cópia dos dados originais do chamador:
static void Main(string[] args)
{
Console.WriteLine("***** Modificadores de Parâmetros *****\n");
// Passa duas variáveis por valor.
int x = 9, y = 10;
Console.WriteLine("Antes da chamada: X: {0}, Y: {1}", x, y);
Console.WriteLine("Resultado: {0}", Somar(x, y));
Console.WriteLine("Após a chamada: X: {0}, Y: {1}", x, y);
Console.ReadLine();
}
Como era de se esperar, os valores de x e y permanecem idênticos antes e após a chamada à função Somar(), como mostrado a seguir:
**** Modificadores de Parâmetros *****
Antes da chamada: X: 9, Y: 10
Resultado: 19
Após a chamada: X: 9, Y: 10
O modificador out de C# serve um propósito muito útil: ele permite ao chamador obter múltiplos valores de retorno de uma única chamada de função.
// Retornando múltiplos parâmetros de saída.
static void PrencherDados(out int a, out string b, out bool c)
{
a = 9;
b = "Esta é sua string.";
c = true;
}
Lembre-se que você deve usar o modificador out não apenas quando você declara o método mas também quando você chama o método.
static void Main(string[] args)
{
Console.WriteLine("***** Modificadores de Parâmetros *****");
...
int i;
string str;
bool b;
PreencherDados(out i, out str, out b);
Console.WriteLine("i: {0}", i);
Console.WriteLine("str: {0}", str);
Console.WriteLine("b: {0}", b);
Console.ReadLine();
}
Como uma última observação a respeito do modificador out, lembre-se que um método que define parâmetros de saída deve atribuir valores válidos para o parâmetro antes de sair de seu escopo. Portanto, o código a seguir irá resultar em erros de compilação, visto que o parâmetro de saída não foi atribuído dentro do escopo do método:
static void IssoNaoIraCompilar(out int a)
{
Console.WriteLine("Erro! Parâmetro de saída não atribuído!");
}
Dados numéricos entram na categoria de tipos de valor. Portanto, se você modificar os valores dos parâmetros dentro do escopo do método essas alterações não serão visíveis para o chamador, pois você está modificando os valores de uma cópia dos dados originais do chamador:
static void Main(string[] args)
{
Console.WriteLine("***** Modificadores de Parâmetros *****\n");
// Passa duas variáveis por valor.
int x = 9, y = 10;
Console.WriteLine("Antes da chamada: X: {0}, Y: {1}", x, y);
Console.WriteLine("Resultado: {0}", Somar(x, y));
Console.WriteLine("Após a chamada: X: {0}, Y: {1}", x, y);
Console.ReadLine();
}
Como era de se esperar, os valores de x e y permanecem idênticos antes e após a chamada à função Somar(), como mostrado a seguir:
**** Modificadores de Parâmetros *****
Antes da chamada: X: 9, Y: 10
Resultado: 19
Após a chamada: X: 9, Y: 10
O Modificador out
Com o modificador de parâmetros out você pode fornecer parâmetros de saída para suas funções. Métodos que são definidos para receber parâmetros de saída (através da palavra chave out) têm a obrigação de atribuir-lhes um valor apropriado antes do fim do escopo do método. Se você não fizer isso, você irá receber erros de compilação.
Para propósitos de ilustração, criamos uma versão alternativa do método Somar() que retorna a soma de dois inteiros utilizando o modificador out de C# (observe que o tipo de retorno do método foi modificado para void).
// Parâmetros de saída devem ser atribuídos pelo método chamado.
static void Somar(int x, int y, out int total)
{
total = x + y;
}
static void Somar(int x, int y, out int total)
{
total = x + y;
}
Para chamar um método com parâmetros de saída também é necessário usar o modificador out. Contudo, as variáveis locais que são passadas como variáveis de saída não precisam ser atribuídas antes de serem passadas como argumentos de saída (se você fizer isso, o valor original será perdido após a chamada). Veja um exemplo abaixo:
static void Main(string[] args)
{
Console.WriteLine("***** Modificadores de Parâmetros *****");
...
// Não é necessário atribuir valores iniciais para parâmetros
// de saída.
int total;
Somar(100, 40, out total);
Console.WriteLine("100 + 40 = {0}", total);
Console.ReadLine();
}
{
Console.WriteLine("***** Modificadores de Parâmetros *****");
...
// Não é necessário atribuir valores iniciais para parâmetros
// de saída.
int total;
Somar(100, 40, out total);
Console.WriteLine("100 + 40 = {0}", total);
Console.ReadLine();
}
O modificador out de C# serve um propósito muito útil: ele permite ao chamador obter múltiplos valores de retorno de uma única chamada de função.
// Retornando múltiplos parâmetros de saída.
static void PrencherDados(out int a, out string b, out bool c)
{
a = 9;
b = "Esta é sua string.";
c = true;
}
Lembre-se que você deve usar o modificador out não apenas quando você declara o método mas também quando você chama o método.
static void Main(string[] args)
{
Console.WriteLine("***** Modificadores de Parâmetros *****");
...
int i;
string str;
bool b;
PreencherDados(out i, out str, out b);
Console.WriteLine("i: {0}", i);
Console.WriteLine("str: {0}", str);
Console.WriteLine("b: {0}", b);
Console.ReadLine();
}
Como uma última observação a respeito do modificador out, lembre-se que um método que define parâmetros de saída deve atribuir valores válidos para o parâmetro antes de sair de seu escopo. Portanto, o código a seguir irá resultar em erros de compilação, visto que o parâmetro de saída não foi atribuído dentro do escopo do método:
static void IssoNaoIraCompilar(out int a)
{
Console.WriteLine("Erro! Parâmetro de saída não atribuído!");
}
O Modificador ref
Considere agora o uso do modificador de parâmetros ref de C#. Parâmetros de referência são necessários quando você deseja permitir a um método operar em (e usualmente modificar) vários pontos de dados declarados dentro do escopo do do chamador (tal como uma rotina de ordenação ou permutação). Note a distinção entre parâmetros de saída e parâmetros de referência:
- Parâmetros de saída não precisam ser inicializados antes de serem passados para o método, pois o método deve atribuir valores a esses parâmetros antes de finalizar.
- Parâmetros de referência devem ser inicializados antes de serem passados para o método. A razão para isso é que você está passando uma referência para uma variável existente. Se você não lhe atribuir um valor inicial, isso seria equivalente a operar com uma variável local não atribuída.
Examinemos o uso da palavra chave ref por meio de um método que troca os valores de duas strings:
// Parâmetros de referência.
public static void TrocarStrings(ref string s1, ref string s2)
{
string auxiliar = s1;
s1 = s2;
s2 = auxiliar;
}
Este método pode ser chamado da seguinte forma:
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Methods *****");
...
string s1 = "C#";
string s2 = "Programmer";
Console.WriteLine("Antes: {0}, {1} ", s1, s2);
TrocarStrings(ref s1, ref s2);
Console.WriteLine("Depois: {0}, {1} ", s1, s2);
Console.ReadLine();
}
Neste exemplo o chamador atribuiu um valor inicial para os parâmetros de referência (s1 e s2). Uma vez que o método TrocarStrings() for executado s1 irá conter o valor "Programmer" e s2 terá o valor "C#".
Antes: C# Programmer
Depois: Programmer C#
public static void TrocarStrings(ref string s1, ref string s2)
{
string auxiliar = s1;
s1 = s2;
s2 = auxiliar;
}
Este método pode ser chamado da seguinte forma:
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Methods *****");
...
string s1 = "C#";
string s2 = "Programmer";
Console.WriteLine("Antes: {0}, {1} ", s1, s2);
TrocarStrings(ref s1, ref s2);
Console.WriteLine("Depois: {0}, {1} ", s1, s2);
Console.ReadLine();
}
Neste exemplo o chamador atribuiu um valor inicial para os parâmetros de referência (s1 e s2). Uma vez que o método TrocarStrings() for executado s1 irá conter o valor "Programmer" e s2 terá o valor "C#".
Antes: C# Programmer
Depois: Programmer C#
O Modificador params
C# suporta vetores de parâmetros através do uso da palavra-chave params. Esta palavra-chave permite a você passar um número variável de parâmetros de mesmo tipo para um método como um único parâmetro lógico.
Por exemplo, considere que você precise criar uma função que permita ao chamador fornecer qualquer número de argumentos e retorna a média dos valores fornecidos. Se você fosse declarar esse método para receber um vetor de doubles, isso forçaria o chamador a primeiro declarar o vetor, preenchê-lo com os valores, e finalmente passá-lo para o método. Contudo, se você programar o método CalcularMedia() para receber um params de tipos de dados double o chamador terá simplesmente que fornecer uma lista de doubles separados por vírgula.
// Retorna a média de um número indefinido de doubles.
static double CalcularMedia(params double[] valores)
{
Console.WriteLine("Você passou {0} doubles.", valores.Length);
double soma = 0;
if(valores.Length == 0)
return soma;
for (int i = 0; i < valores.Length; i++)
soma += soma[i];
return (soma / valores.Length);
}
Esse método foi definido para receber um vetor de parâmetros double. Para utilizar esse método você usaria um código semelhante ao seguinte:
static void Main(string[] args)
{
Console.WriteLine("***** Modificadores de Parâmetros *****");
...
// Passa uma lista de doubles separados por vírgula...
double media;
media = CalcularMedia(4.0, 3.2, 5.7, 64.22, 87.2);
Console.WriteLine("A média desses valores é: {0}", media);
// ...ou passa um vetor de doubles
double[] valores = { 4.0, 3.2, 5.7 };
media = CalcularMedia(valores);
Console.WriteLine("A média desses valores é: {0}", media);
// A média de 0 é 0!
Console.WriteLine("A média desses valores é: {0}", CalcularMedia();
C# permite a declaração de somente um argumento params, e esse de ver o último argumento do método.
static double CalcularMedia(params double[] valores)
{
Console.WriteLine("Você passou {0} doubles.", valores.Length);
double soma = 0;
if(valores.Length == 0)
return soma;
for (int i = 0; i < valores.Length; i++)
soma += soma[i];
return (soma / valores.Length);
}
Esse método foi definido para receber um vetor de parâmetros double. Para utilizar esse método você usaria um código semelhante ao seguinte:
static void Main(string[] args)
{
Console.WriteLine("***** Modificadores de Parâmetros *****");
...
// Passa uma lista de doubles separados por vírgula...
double media;
media = CalcularMedia(4.0, 3.2, 5.7, 64.22, 87.2);
Console.WriteLine("A média desses valores é: {0}", media);
// ...ou passa um vetor de doubles
double[] valores = { 4.0, 3.2, 5.7 };
media = CalcularMedia(valores);
Console.WriteLine("A média desses valores é: {0}", media);
// A média de 0 é 0!
Console.WriteLine("A média desses valores é: {0}", CalcularMedia();
Console.ReadLine();
}
Nenhum comentário:
Postar um comentário