Os métodos da aula anterior eram autossuficientes, mas rígidos: cada um fazia sempre exatamente a mesma coisa, sem receber informação nem devolver resultado. Um método ExibirBoasVindas sempre exibia a mesma mensagem. Isso é útil, mas limitado. Os métodos verdadeiramente poderosos comunicam-se com o mundo ao redor: recebem dados para trabalhar e devolvem resultados. Um método CalcularMedia precisa receber as notas e devolver a média; um Saudar fica muito mais útil se receber o nome de quem saudar. Nesta aula, aprenderemos as duas pontas dessa comunicação: os parâmetros, que são a informação que um método recebe, e o retorno, que é o valor que ele devolve. Com elas, os métodos deixam de ser blocos fixos e tornam-se ferramentas flexíveis, que se adaptam aos dados que você lhes entrega.
Parâmetros: a informação que entra
Um parâmetro é uma informação que um método recebe para poder fazer seu trabalho. Você já os usou o tempo todo: quando escreve Console.WriteLine("Olá"), o texto "Olá" é um argumento que você entrega ao método, e ele exibe justamente aquilo que recebeu. Agora aprenderemos a criar métodos que recebem informações desse modo.
Os parâmetros são declarados dentro dos parênteses da definição do método, cada um com seu tipo e seu nome — exatamente como se declara uma variável. Veja um método que recebe um nome e o saúda:
// O parâmetro 'nome', do tipo string, é declarado entre os parênteses.
void Saudar(string nome)
{
Console.WriteLine($"Olá, {nome}! Seja bem-vindo.");
}
// Nas chamadas, entregamos um ARGUMENTO para o parâmetro:
Saudar("Ana"); // exibe: Olá, Ana! Seja bem-vindo.
Saudar("Carlos"); // exibe: Olá, Carlos! Seja bem-vindo.
Observe o poder que isso traz. O método Saudar é definido uma vez, mas produz saudações diferentes conforme o nome que recebe — "Ana" numa chamada, "Carlos" na outra. O parâmetro nome funciona como uma variável interna ao método, que assume, a cada chamada, o valor que lhe foi entregue. Dentro do método, usamos nome normalmente, sem saber (nem precisar saber) qual valor específico virá — o método funciona corretamente para qualquer nome. Essa é a flexibilidade que os parâmetros conferem: um método, muitos comportamentos, conforme os dados recebidos.
Vale distinguir dois termos que se confundem: parâmetro é o nome declarado na definição do método (o nome em void Saudar(string nome)); argumento é o valor concreto entregue na chamada (o "Ana" em Saudar("Ana")). Na prática, muitos usam os termos de forma intercambiável, mas a distinção é: o parâmetro é a "gaveta de entrada" declarada; o argumento é o que você põe nela ao chamar.
Vários parâmetros
Um método pode receber vários parâmetros, separados por vírgula, cada um com seu tipo e nome. Veja um método que exibe os dados de uma pessoa, recebendo três informações:
void ExibirFicha(string nome, int idade, string cidade)
{
Console.WriteLine($"Nome: {nome}");
Console.WriteLine($"Idade: {idade}");
Console.WriteLine($"Cidade: {cidade}");
}
// Na chamada, os argumentos são entregues na MESMA ORDEM dos parâmetros:
ExibirFicha("Ana", 30, "Recife");
Um ponto crucial: os argumentos são associados aos parâmetros pela ordem. Na chamada ExibirFicha("Ana", 30, "Recife"), o primeiro argumento ("Ana") vai para o primeiro parâmetro (nome), o segundo (30) para o segundo (idade), e assim por diante. Se você trocar a ordem — escrevendo, digamos, ExibirFicha(30, "Ana", "Recife") —, o C# tentará colocar o número 30 no parâmetro nome (que espera texto) e reclamará, ou, em casos onde os tipos coincidem, produzirá um resultado errado silenciosamente. A ordem dos argumentos deve corresponder à ordem dos parâmetros; é uma correspondência posicional que você deve respeitar.
Retorno: o valor que sai
A outra ponta da comunicação é o retorno: um valor que o método devolve a quem o chamou, para ser usado. Um método void, como vimos, não devolve nada — apenas faz. Mas um método que calcula algo precisa entregar o resultado desse cálculo de volta. Para isso, na definição, trocamos o void pelo tipo do valor que será devolvido, e usamos a palavra return para efetivamente devolvê-lo:
// Em vez de 'void', declaramos 'int': este método devolve um número inteiro.
int Somar(int a, int b)
{
int resultado = a + b;
return resultado; // devolve o resultado a quem chamou
}
// A chamada agora PRODUZ um valor, que podemos guardar ou usar:
int total = Somar(5, 3); // 'total' recebe o valor devolvido: 8
Console.WriteLine(total); // exibe: 8
Console.WriteLine(Somar(10, 20)); // ou usamos o valor diretamente: exibe 30
Acompanhe o que acontece. O método Somar recebe dois números, calcula sua soma, e a devolve com return. Na chamada Somar(5, 3), o método executa, e a expressão Somar(5, 3) torna-se o valor devolvido, 8 — de modo que podemos guardá-lo numa variável (int total = Somar(5, 3)) ou usá-lo diretamente numa outra expressão. É exatamente como acontecia com int.Parse ou Console.ReadLine, que também devolviam valores que guardávamos; agora você entende o mecanismo por trás: aqueles são métodos com retorno, como o seu Somar.
A palavra return faz duas coisas ao mesmo tempo: define o valor a devolver, e encerra imediatamente o método — nenhuma instrução após o return (dentro daquele método) é executada. O tipo declarado na definição (o int em int Somar(...)) deve corresponder ao tipo do valor devolvido: um método declarado como int deve devolver um int, um declarado como string deve devolver uma string, e assim por diante. Se você declarar um tipo de retorno mas esquecer de devolver um valor com return, o C# reclamará — ele exige que um método que promete devolver algo realmente o faça.
Juntando tudo: um método completo e útil
Vejamos parâmetros e retorno trabalhando juntos num método genuinamente útil — calcular a média de três notas:
double CalcularMedia(double nota1, double nota2, double nota3)
{
double soma = nota1 + nota2 + nota3;
return soma / 3; // devolve a média
}
// Usando o método:
double media = CalcularMedia(8.0, 6.5, 7.0);
Console.WriteLine($"A média é {media}"); // exibe: A média é 7.166...
// O resultado pode até ser usado numa decisão:
if (CalcularMedia(4.0, 5.0, 3.0) >= 6.0)
Console.WriteLine("Aprovado");
else
Console.WriteLine("Reprovado");
Este método CalcularMedia é a síntese da aula: ele recebe três notas (parâmetros) e devolve a média (retorno). Uma vez definido, pode ser usado em qualquer lugar, com quaisquer notas, e seu resultado pode ser guardado, exibido, ou usado numa condição — como no if do exemplo, que chama o método e decide com base no valor devolvido. Escrevemos a lógica da média uma vez, corretamente (com os parênteses certos, lembrando a lição de depuração da aula anterior!), e a reutilizamos com confiança. Este é o método em sua forma plena: uma ferramenta nomeada, flexível pelos parâmetros e útil pelo retorno.
Os métodos deixaram de ser blocos fixos e passaram a ser peças conectáveis. Com parâmetros, um método recebe dados de fora e opera sobre valores diferentes a cada chamada; com retorno, ele devolve um resultado que pode ser guardado, exibido ou usado como entrada de outra operação.
É essa combinação que transforma métodos em peças de construção de verdade. Um método que recebe e devolve pode ser encaixado em qualquer lugar onde um valor daquele tipo faça sentido, e programas grandes são feitos exatamente assim: pequenas unidades bem definidas, cada uma resolvendo um pedaço, combinadas para resolver o todo.
Fontes e leituras recomendadas
- Métodos: parâmetros e argumentos — a referência oficial sobre a passagem de informação a métodos; a base desta aula.
- A instrução return — os detalhes de como um método devolve um valor e encerra sua execução.
- Valores de retorno de métodos — como declarar e usar o tipo de retorno de um método.
- Passagem de argumentos — a correspondência posicional entre argumentos e parâmetros.
- Parâmetros nomeados e opcionais — recursos adicionais de passagem de argumentos, para aprofundar depois.
Exercícios
Exercício 1
Escreva um método void Cumprimentar(string nome, string periodo) que exiba uma saudação como "Bom dia, Ana!" combinando o período e o nome recebidos. Chame-o algumas vezes com valores diferentes e observe como a saída se adapta aos argumentos.
Ver resposta
✓ Resposta: Exemplo:
void Cumprimentar(string nome, string periodo)
{
Console.WriteLine($"Bom {periodo}, {nome}!");
}
Cumprimentar("Ana", "dia"); // Bom dia, Ana!
Cumprimentar("Carlos", "tarde"); // Bom tarde, Carlos!
A saída se adapta porque os parâmetros nome e periodo assumem, a cada chamada, os valores dos argumentos entregues, e o método os usa na mensagem — um método, várias saudações.
Exercício 2
Escreva um método int Dobro(int numero) que receba um número e devolva o seu dobro. Use-o guardando o resultado numa variável, e depois use-o diretamente dentro de um Console.WriteLine. Explique a diferença entre um método void e um método com retorno.
Ver resposta
✓ Resposta: Exemplo:
int Dobro(int numero)
{
return numero * 2;
}
int resultado = Dobro(5); // guarda o valor devolvido: 10
Console.WriteLine(resultado); // 10
Console.WriteLine(Dobro(8)); // usa o valor diretamente: 16
A diferença: um método void apenas executa ações e não devolve nada, então sua chamada não produz um valor para guardar ou usar; um método com retorno (como Dobro, que devolve int) produz um valor que pode ser guardado numa variável ou usado em outra expressão. A chamada de um método com retorno é, ela própria, um valor.
Exercício 3
Explique, com suas palavras, a diferença entre parâmetro e argumento, usando o método Somar(int a, int b) e a chamada Somar(4, 7) como exemplo. Quais são os parâmetros e quais são os argumentos?
Ver resposta
✓ Resposta: No método Somar(int a, int b), os parâmetros são a e b — os nomes declarados na definição, que funcionam como gavetas de entrada. Na chamada Somar(4, 7), os argumentos são 4 e 7 — os valores concretos entregues ao método. Assim, o argumento 4 é colocado no parâmetro a, e o argumento 7 no parâmetro b (pela ordem). Em resumo: parâmetros são declarados na definição; argumentos são fornecidos na chamada.
Exercício 4
Escreva um método bool EhMaiorDeIdade(int idade) que receba uma idade e devolva true se for 18 ou mais, e false caso contrário. Depois, use o valor devolvido diretamente na condição de um if. Explique por que um método pode devolver um bool, e como isso é útil.
Ver resposta
✓ Resposta: Exemplo:
bool EhMaiorDeIdade(int idade)
{
return idade >= 18;
}
if (EhMaiorDeIdade(20))
Console.WriteLine("Pode entrar.");
else
Console.WriteLine("Acesso negado.");
Um método pode devolver um bool porque bool é um tipo como qualquer outro, e a expressão idade >= 18 já produz um verdadeiro/falso, que o return devolve. Isso é útil porque permite encapsular uma pergunta com nome descritivo (EhMaiorDeIdade) e usar seu resultado diretamente numa condição de if, deixando o código mais legível do que repetir a comparação idade >= 18 em vários lugares.
Exercício 5
Analise o método a seguir e explique por que a última linha nunca é executada:
int Testar(int x)
{
return x * 2;
Console.WriteLine("Cheguei aqui?");
}
Ver resposta
✓ Resposta: A linha Console.WriteLine("Cheguei aqui?") nunca é executada porque ela está depois de um return. A instrução return faz duas coisas: devolve o valor (aqui, x * 2) e encerra imediatamente o método — a execução sai do método naquele ponto, e nenhuma instrução posterior é alcançada. Como o return está na linha anterior, o controle já saiu do método antes de chegar ao Console.WriteLine, tornando-o inatingível. (O compilador, aliás, costuma avisar sobre esse "código inalcançável".)