Parâmetros e Retorno: Métodos que Recebem e Devolvem

Parâmetros e Retorno: Métodos que Recebem e Devolvem

O que transforma métodos em peças de construção: os parâmetros, que permitem receber dados diferentes a cada chamada, e o retorno, que devolve um resultado aproveitável. A aula mostra métodos com vários parâmetros e como combinar entrada e saída num método completo e útil.
Linguagem C#

• • 10 min de leitura

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

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".)

Comentários

Mais em Linguagem C#

Projeto Capstone: Reunindo Tudo
Projeto Capstone: Reunindo Tudo

O projeto que integra o curso inteiro: um gerenciador de tarefas completo, com…

Métodos de Objeto e a Palavra this
Métodos de Objeto e a Palavra this

Como dar comportamento aos objetos: métodos que operam sobre o estado do…

Escopo de Variáveis: Onde Cada Variável Existe
Escopo de Variáveis: Onde Cada Variável Existe

Por que uma variável declarada dentro de um método não existe fora dele. A…