O TEMA DO FÓRUM ESTÁ EM MANUTENÇÃO. FEEDBACKS AQUI: ACESSAR

C# para iniciantes - Métodos

Iniciado por MayLeone, 08/09/2017 às 14:08

O que são métodos?
Métodos são sequências de instruções, essas instruções são definidas a partir de uma lista de comandos que poderão ser executadas em ordem, assim que o método for solicitado.
Os métodos são úteis para otimizar o seu código de forma que seu trabalho se torne dinâmico e prático, pois eles tem como função organizar seu programa em partes, separadas por blocos de tarefas.
Por exemplo, digamos que esteja programando um jogo de cartas. Esse jogo precisará de instruções para iniciar, definir os jogadores, embaralhar as cartas e distribuí-las, correto?
Ao invés de você programar todas essas instruções tudo de uma vez, o mais interessante e prático seria separar cada "função" do programa a partir de métodos, por exemplo:



Outra vantagem de utilizar os métodos em sua programação é a produtividade no código.
Você pode criar um método para executar uma sequência de instruções que poderão ser utilizadas em diversos momentos da sua programação, ou seja, ao invés de programar novamente aquela mesma sequência, você simplesmente a programa uma vez dentro do método, e a partir disto apenas o chama para que ele execute a lista de comandos quantas vezes forem necessárias.




Como criar métodos?
Os métodos são criados a partir de um nome antecedido por alguns atributos, por exemplo:



Vamos por partes, onde será explicado o que cada atributo significa:




  • Acesso:
A palavra "public" é o modificador de acesso do seu método, ou seja, onde seu método poderá ser chamado e acessado.
Se for public (público) este método poderá ser chamado a partir de qualquer classe externa (ou seja, que não contém este método definido).
Se for private (privado) o método só poderá ser chamado dentro da classe que ele foi criado.
Não se preocupe em pensar nisto agora, o final deste documento trará uma breve explicação e exemplo prático da diferença entre esses tipos de acesso.
O método nem sempre precisa ser definido com esta informação, você pode escrever o seu método sem as palavras reservadas de acesso, por exemplo:




  • Instância do método:
A palavra "static" (estático) ao ser utilizada na definição do seu método, faz com que o mesmo não necessite ser instanciado (criar uma "cópia" dele dentro de um objeto) para que ele possa ser chamado.
Normalmente definimos métodos estáticos quando estamos utilizando o console de aplicações do Visual Studio, onde não existe a necessidade de instanciamento de métodos para que sejam utilizados.
Porém, este assunto sobre instâncias será melhor abordado em aulas futuras, então não fique com receio se não compreendeu muito bem esta explicação por agora.
Esse atributo também pode ser omitido no momento da criação do método, fazendo com que o mesmo não seja estático, bastando não escrever essa palavra reservada no momento de criação do método:




  • Tipo de retorno:
Quando um método for criado é importante que seja definido seu tipo de retorno, ou seja, qual o tipo de objeto que ele vai retornar para seu chamador.
Os tipos de retornos podem ser definidos como as variáveis: int para inteiros, float/decimal/double para números quebrados, char ou string para textos ou caractere e também bool, que retornará um valor verdadeiro (true) ou falso (false).
O retorno de um método é como se fosse o "resultado final" do seu processo que será devolvido dentro de uma variável, por exemplo.
Não se preocupe, pois no exemplo prático sobre a utilização de métodos você entenderá melhor este conceito de "retorno".
Sempre que definir um método que possui algum valor a ser retornado, é indispensável a utilização da palavra reservada "return" em algum momento do seu método, fazendo com que este comando retorne o valor desejado.
Às vezes um método não vai ter a necessidade de retornar um valor, então quando for este o caso, o tipo de retorno deve ser vazio (void):




  • Nome do método:
O nome para o método é obviamente obrigatório no momento de sua criação, pois será a partir deste nome que ele será identificado pelo compilador.
A nomeação do método fica a cargo do programador, e segue as mesmas regras de "nomeação" de variáveis:
1. Não iniciar com números e caracteres especiais;
2. Não conter acentuações;
3. Não utilizar espaços nem pontos para separar suas palavras;
4. Não possuir o nome de outro método já existente.


  • Parâmetros:
Os métodos após seu nome devem sempre possuir os parênteses "()" para que funcionem corretamente.
Dentro desses parênteses devem conter os parâmetros do seu método, que nada mais são que as informações que serão passadas para o método, indicando com o que ele vai trabalhar.
Os parâmetros devem ter um tipo (assim como os tipos de retornos) e devem ser separados por vírgulas caso forem mais de um:



Nem sempre o método precisa possuir parâmetros, nesse caso os parênteses devem estar vazios:



Como já dito neste documento, os métodos não são nada mais que uma sequência de instruções (blocagem de códigos), portanto devem iniciar com uma chave aberta "{" e terminar com a chave fechada "}", assim como fazemos com as estruturas condicionais e de repetições.




Utilizando Métodos:
Agora vamos utilizar todos os conceitos apresentados acima com alguns exemplos da aplicação dos métodos e o seu uso na programação.
Vamos abrir o console de aplicação do Visual Studio para que possamos trabalhar com nossos códigos.
O primeiro exemplo seria criar uma calculadora bem simples que apenas calcula com duas variáveis. Essa calculadora vai solicitar o valor das variáveis e qual operação será realizada.
Você poderia criar este programa sem o uso dos métodos, porém se desejasse calcular mais de duas variáveis distintas iria ter de realizar o processo de cálculo novamente, porém com o método você só o programa uma vez e o reutiliza para outras variáveis:
Dentro do método Main crie as duas varáveis que serão calculadas:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
float var1 = 0, var2 = 0;
}
}
}


Agora vamos criar nosso método fora do método Main (normalmente não se cria métodos dentro de outros métodos).
Como estamos no console de aplicações, o método deve ser estático.
Ele não vai nos retornar valor algum e seus parâmetros devem ser do tipo float (assim como as variáveis que criamos) para que o método realize as operações com elas:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
float var1 = 0, var2 = 0;
}
static void Calculadora(float numero1, float numero2)
{
}
}
}


Agora devemos cobrar do usuário os valores a serem calculados e a operação matemática a ser realizada. Faremos isto dentro do método através dos consoles de entrada e saída de dados (ReadLine e WriteLine):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
float var1 = 0, var2 = 0;
}
static void Calculadora(float numero1, float numero2)
{
string operacao = "";
float resultado = 0;
Console.WriteLine("Informe o primeiro valor");
numero1 = float.Parse(Console.ReadLine());
Console.WriteLine("Informe a operação matemática a ser realizada");
operacao = Console.ReadLine();
Console.WriteLine("Informe o segundo valor");
numero2 = float.Parse(Console.ReadLine());
}
}
}


Podemos criar uma estrutura condicional para verificar qual operação foi solicitada, e dentro dela executar as operações de soma, subtração, multiplicação e divisão.
Também podemos exibir no final do método o resultado da operação, finalizando seu bloco:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
float var1 = 0, var2 = 0;
}
static void Calculadora(float numero1, float numero2)
{
string operacao = "";
float resultado = 0;
Console.WriteLine("Informe o primeiro valor");
numero1 = float.Parse(Console.ReadLine());
Console.WriteLine("Informe a operação matemática a ser realizada");
operacao = Console.ReadLine();
Console.WriteLine("Informe o segundo valor");
numero2 = float.Parse(Console.ReadLine());
switch (operacao)
{
case "+":
resultado = numero1 + numero2;
break;
case "-":
resultado = numero1 - numero2;
break;
case "*":
resultado = numero1 * numero2;
break;
case "/":
if (numero2 != 0){resultado = numero1 / numero2;}
else { Console.WriteLine("Não é possível dividir por zero!"); }
break;
default:
Console.WriteLine("ERRO: Não foi informado um operador");
Console.ReadLine();
Console.Clear();
return;
}
Console.WriteLine("{0} {1} {2} = {3}", numero1, operacao, numero2, resultado);
Console.ReadKey();
}
}
}


Apesar de nosso método estar feito, ele não será executado sozinho. Para que ele possa iniciar seus comandos e suas instruções ele deve ser chamado.
Para chamar seu método, basta escrever seu nome e passar os argumentos a ele que devem estar entre os parênteses após o seu nome.
Como vamos calcular as variáveis "var1" e var2" elas serão nossos argumentos na chamada do método:



Ao rodar o debug do seu código, você terá algo mais ou menos dessa forma:



Perceba que ao chamar o método "Calculadora", você o executa e tudo o que está dentro de sua blocagem de códigos será executada na sequência em que foi programada.
Note também que você utilizou as variáveis "var1" e "var2" como argumentos de chamada do método.
Quando você define os argumentos, eles automaticamente são substituídos pelos parâmetros do seu método, que seriam "numero1" e "numero2".

Se for perceber, no método são utilizadas estas variáveis para realizar os cálculos, veja nesta linha do código:


Isso significa que não importa quais variáveis você queira calcular, sempre que você chamar o método, o que será calculado serão as variáveis passadas como argumentos, o que nos possibilita utilizar esse método mais de uma vez para várias variáveis diferentes, evitando que você repita o código para executar o mesmo procedimento.
Experimente criar duas novas variáveis do tipo flutuante, passando-as como argumentos ao chamar novamente o método "Calculadora":

static void Main(string[] args)
{
float var1 = 0, var2 = 0, var3 = 0, var4 = 0;
Calculadora(var1, var2);
Calculadora(var3, var4);
}


Veja que ao rodar o debug você poderá utilizar a calculadora duas vezes, com quatro variáveis diferentes, sem ter tido que reprogramar essa calculadora para as novas variáveis:



Outra coisa que vale a pena notar em nosso código é a condição "default", onde se o usuário não entrar com algum operador matemático válido, essa linha de código será executada:



Uma mensagem de erro será exibida no console de execução, e quando o usuário pressionar a tecla 'enter' a tela vai ser limpa através do método Console.Clear();
Veja também que utilizamos o "return" para sair de dentro do método.
Como nosso método não retorna valores (possui retorno vazio [void]), podemos utilizar o return para sair do método assim que ele for chamado, dessa forma, se o usuário não informar o operador matemático, a exibição do resultado da operação não será executada, pois o return foi chamado antes disso, evitando algum tipo de bug, não exibindo nenhum valor de cálculo.

Acho que já conseguiu perceber uma das vantagens de se utilizar métodos em seus programas, não? Pois como vimos aqui, podemos reaproveitar todas as instruções da nossa calculadora a qualquer momento do código em que o método for solicitado, e com diversas variáveis diferentes, apenas bastando passa-las em seu argumento de chamada. Simples, não é verdade?



Métodos com retornos:
Logo acima nós vimos como trabalhar com métodos que não retornam valores e são criados como "void".
Agora vou mostrar uma aplicação simples de como podemos utilizar um método que retorna algum valor.
Como exemplo, vamos criar um programa que procure pelo maior valor inserido numa array de vetor.
Supondo que por algum motivo em nossa programação nós vamos precisar utilizar esse elemento para alguma validação no código.

Se o método que procura pelo maior elemento no vetor não tivesse um retorno, ele apenas iria processar essa função para nós, mas não poderíamos utilizar esse elemento porque ele estaria apenas dentro do método.
Para que possamos manipular o elemento que foi encontrado dentro do nosso método, sem termos que fazer isso no próprio método, mas sim em qualquer local de nosso código, nós devemos retorná-lo após o método encerrar sua execução, assim podemos utilizá-lo em aplicações futuras em nosso programa.
Vamos então criar uma array de inteiros dentro do nosso método Main, para que ela seja usada como argumento.
Você também pode utilizar o console de saída para que o usuário possa definir o tamanho desse vetor.

Crie nosso método como estático, com tipo de retorno de inteiros (pois ele vai retornar o maior elemento do vetor, que será um inteiro). Passe também o parâmetro que seria o vetor que vai ser verificado:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Qual será o tamanho do vetor?");
int tamanho = int.Parse(Console.ReadLine());
int[] ConjuntoDeNumeros = new int[tamanho];
}
static int MaiorValor(int[] vetor)
{
}
}
}


Não se preocupe se o tracejado vermelho permanecer abaixo do nome do seu método, ele vai desaparecer assim que você utilizar o "return" no código.
Agora dentro do método vamos utilizar os consoles de entrada e saída de dados para armazenarmos valores dentro dos índices desse vetor, utilizando um laço para que o diálogo seja programado apenas uma vez.

Para que possamos verificar qual o maior elemento inserido neste vetor, precisamos criar um novo laço que cheque cada índice do vetor.
Dentro desse laço criamos uma condição que verifica se o elemento do índice do vetor que está atualmente no contador é maior que o elemento guardado dentro de uma variável que criamos no início do método, a variável "ValorEncontrado". Se o elemento dentro do índice do vetor for maior que o valor de "ValorEncontrado" essa variável passa a receber o valor do elemento do vetor, caso não, o laço apenas faz um incremento no índice deste vetor.
Após o laço percorrer todas as posições do vetor, o maior valor dentro dele vai ter sido encontrado, então podemos retorná-lo do método através do comando "return":

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Qual será o tamanho do vetor?");
int tamanho = int.Parse(Console.ReadLine());
int[] ConjuntoDeNumeros = new int[tamanho];
}
static int MaiorValor(int[] vetor)
{
int ValorEncontrado = 0;
for (int loop = 0; loop < vetor.Length; loop++)
{
Console.WriteLine("Adicione um inteiro no vetor");
vetor[loop] = int.Parse(Console.ReadLine());
}
for (int i = 0; i < vetor.Length; i++)
{
if (i == 0) { ValorEncontrado = vetor[0]; }
if (vetor[i] > ValorEncontrado)
{
ValorEncontrado = vetor[i];
}
}
return ValorEncontrado;
}
}
}


Agora que terminamos de programar a lógica de nosso método, podemos chama-lo através do método Main.
Já que temos um valor a ser retornado deste método, podemos armazená-lo numa variável no momento de sua chamada, dessa forma essa variável passará a armazenar o valor retornado de nosso método, e assim poderá ser utilizada em algum momento em nosso código.
Para testar a eficiência do nosso método, podemos utilizar o console de saída para exibirmos o maior elemento encontrado em nosso vetor:

static void Main(string[] args)
{
Console.WriteLine("Qual será o tamanho do vetor?");
int tamanho = int.Parse(Console.ReadLine());
int[] ConjuntoDeNumeros = new int[tamanho];
int ValorRetornado = MaiorValor(ConjuntoDeNumeros);
Console.WriteLine("O maior elemento encontrado neste vetor é: {0}", ValorRetornado);
Console.ReadKey();
}


Debugue o código, escolha um tamanho qualquer para seu vetor, adicione valores dentro dele e obtenha o resultado do maior valor inserido a ele:



Veja que podemos utilizar esse método para quantos vetores quisermos analisar, sendo assim, crie um novo vetor com tamanho qualquer (eu criei com tamanho 3 para exemplificar).

Note que eu posso chamar o mesmo método para dois vetores distintos, apenas passando seus argumentos:

Console.WriteLine("Qual será o tamanho do vetor?");
int tamanho = int.Parse(Console.ReadLine());
int[] ConjuntoDeNumeros = new int[tamanho];
int[] OutroConjunto = new int[3];
int ValorRetornado = MaiorValor(ConjuntoDeNumeros);
Console.WriteLine("\n Trabalhando com outro vetor de tamanho 3 \n");
int OutroValorRetornado = MaiorValor(OutroConjunto);


Agora veja a utilidade de um retorno do método: Eu posso armazenar na variável do chamador do método o maior elemento encontrado neste vetor e com ele fazer comparações:

if (ValorRetornado > OutroValorRetornado)
{
Console.WriteLine("O elemento {0} do vetor 1 é maior que o elemento {1} do vetor 2", ValorRetornado, OutroValorRetornado);
}
else if (ValorRetornado < OutroValorRetornado)
{
Console.WriteLine("O elemento {1} do vetor 2 é maior que o elemento {0} do vetor 1", ValorRetornado, OutroValorRetornado);
}
else
{
Console.WriteLine("O elemento {0} do vetor 1 é igual o elemento do vetor 2", ValorRetornado);
}
Console.ReadKey();
}


Debugue mais uma vez este programa e veja o resultado. Ele vai comparar qual dos maiores elementos dos vetores é maior entre eles:



Por fim, você quem vai decidir de acordo com a sua necessidade se o método terá retorno, parâmetros e se será estático ou não.




Modificador de acesso do Método:
E como prometido, vou passar uma breve explicação das diferenças entre os acessos dos métodos em suas classes.
Veja um exemplo rápido de acessibilidade de um método:
No código abaixo temos duas classes definidas, uma delas contém o método "Exemplo" criado como public.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program // Classe program
{
static void Main(string[] args)
{
Teste.Exemplo(); /* Chamada do método sem nenhum tipo de erro, mesmo ele estando em outra classe diferente.
* Veja que para chamar o método de outra classe eu apenas preciso informar a classe que ele está inserido e chamar por seu nome.
* Como o método é estático, não preciso criar uma instância dele para sua chamada! */
}
}
class Teste // Nova classe criada, externa à classe 'Program'
{
public static void Exemplo() // Método público
{
// Instruções do método aqui
}
}
}


Agora vejamos o que acontece se eu trocar o modificador de acesso desse método de "public" para "private":



Note que agora vemos um tracejado vermelho quando chamamos pelo método privado fora da classe de onde ele foi criado.
Perceba que o erro diz algo como "Teste.Exemplo() é inacessível por conta de seu nível de proteção", ou seja, ele não pode ser chamado nessa classe porque ele é privado, só poderá ser chamado na classe em que foi criado.
Existem outros tipos de modificadores de acesso de um método, mas com certeza os principais são o "public" e "private", porém no decorrer das aulas nós veremos os outros tipos e também saberemos para o que cada um é utilizado.



Final da aula sobre métodos
Download PDF deste documento aqui.