Sub-rotinas: procedimentos e funções - 1


Uma sub-rotina é uma parte separada de um programa que tem um nome e resolve sua própria tarefa separada. A sub-rotina está localizada no início do programa principal e pode ser iniciada (chamada) a partir do programa principal especificando o nome.

O uso de sub-rotinas permite evitar a duplicação de código se você precisar escrever o mesmo código em programas de lugares diferentes . 
As bibliotecas que são importadas para um programa (por exemplo, Sistema) consistem em rotinas que já foram compiladas por alguém. Os programadores não precisam pensar em quais algoritmos são implementados neles, eles apenas os aplicam, pensando apenas no que exatamente estão fazendo. Esta é uma grande economia de tempo. Não há necessidade de escrever um algoritmo que já foi escrito por outra pessoa.

Cada sub-rotina deve executar apenas uma tarefa, seja calcular algo, produzir alguns dados ou fazer outra coisa. 

As sub-rotinas, ou métodos, são de dois tipos -  funções (aquelas que retornam o resultado do trabalho) e procedimentos (aquelas que não retornam).

Vamos começar com o segundo tipo. Vamos tentar escrever um exemplo simples.
Suponha que precisamos exibir a string "Error" na tela sempre que pode ocorrer um erro no código por falha do usuário (por exemplo, quando ele insere dados incorretos).
Isso pode ser feito escrevendo a declaração
Console.WriteLine("Error"); Agora vamos imaginar que esta linha precisa ser inserida em vários lugares no programa. Claro, você pode simplesmente escrevê-lo em todos os lugares. Mas esta solução tem duas desvantagens.
1) esta string será armazenada na memória muitas vezes;
2) se quisermos alterar a saída em caso de erro, teremos que alterar esta linha ao longo do programa, o que é bastante inconveniente.

Para tais casos, métodos e procedimentos são necessários.
Um programa com um procedimento pode ser assim:

usando Sistema;
classProgram {
    static void PrintError() {
        Console.WriteLine("Erro");
    }
    static void Main() {
        PrintError();
    }
}

 

Um procedimento começa com a palavra void. Após a nome do procedimento  colchetes vazios são escritos.
Todas as instruções executadas em um procedimento são recuadas. 
O modificador Static  significa que o determinado campo, método ou propriedade não pertencerá a cada objeto da classe, mas a todos eles juntos.
Métodos e procedimentos são escritos antes do método principal Main().

Para se referir a um procedimento, no programa principal você precisa chamá-lo pelo nome e não se esqueça de colocar parênteses.
Você pode chamar um procedimento em um programa quantas vezes quiser.

Agora vamos imaginar que precisamos exibir diferentes mensagens em resposta a um erro do usuário, dependendo se exatamente o erro que ele cometeu.
Nesse caso, você pode escrever seu próprio procedimento para cada erro: 

 

void imprimirErroZero() {     Console.WriteLine("Erro. ​​Divisão por zero!"); }

 

 

void printErrorInput() { Console.WriteLine("Erro na entrada!"); } E se houver muitos outros erros possíveis? Então esta solução não nos convém.
Precisamos aprender a controlar o procedimento, informando qual mensagem de erro exibir.
Para fazer isso, precisamos de parâmetros que escreveremos entre parênteses após o nome do procedimento
void printError(string s) { Console.WriteLine(s); } Neste procedimento, s é um parâmetro - uma variável especial que permite controlar o procedimento.
O parâmetro é uma variável de cujo valor depende o funcionamento da sub-rotina. Os nomes dos parâmetros são listados separados por vírgulas no cabeçalho do subprograma. O tipo de parâmetro é escrito antes do parâmetro.

Agora, ao chamar o procedimento, você precisa especificar o valor real entre parênteses que será atribuído ao parâmetro (a variável s) dentro do nosso procedimento printError("Erro! Divisão por zero!"); Este valor é chamado de argumento.
O argumento é o valor do parâmetro que é passado para a sub-rotina quando ela é chamada.
O argumento pode ser não apenas um valor constante, mas também uma variável ou uma expressão aritmética.< /span>< /span>

Variáveis ​​locais e globais
Muitas vezes é necessário utilizar variáveis ​​adicionais que serão utilizadas somente na sub-rotina. Tais variáveis ​​são chamadas de locais (ou locais) e só podem ser manipuladas dentro da sub-rotina em que são criadas.
 
Escopo de variável local é o bloco entre colchetes no qual ela é declarada.
O programa principal em C# também é uma sub-rotina, então todas as variáveis ​​declaradas dentro de void Main() são variáveis ​​locais. Outras sub-rotinas não "sabem" nada sobre as variáveis ​​locais de outras sub-rotinas.

Assim, é possível limitar o escopo (scope) de uma variável apenas à sub-rotina onde ela é realmente necessária. Na programação, essa técnica é chamada de encapsulamento  - ocultando a variável de alterá-la de fora.

Se for necessário declarar uma variável que seria visível em qualquer lugar do programa (em qualquer sub-rotina), então tais variáveis ​​são declaradas fora de todas as sub-rotinas (ver programa 3 da tabela abaixo).
Essas variáveis ​​são chamadas de globais.

Em C#, quando o programa inicia, todas as variáveis ​​globais são automaticamente zeradas (as variáveis ​​booleanas assumem o valor false).

Analise três programas:
1) Neste programa, a variável i é local. Uma variável local é declarada dentro de uma sub-rotina. 2) Aqui, mesmo que exista uma variável i no programa principal (com valor 7), uma nova variável local i com valor 5 será criada. 
Quando este programa for executado, o valor 75 aparecerá na tela.
3) Este programa tem uma variável global i. Seu valor pode ser alterado dentro da sub-rotina, e dentro do programa principal.
O procedimento funcionará com a variável global i e será atribuído a ela um novo valor igual a 2. O valor 2 é exibido.
teste de vazio estático () {   int i = 5; Console.Write("i"); } teste de vazio estático () {   int i = 5;   Console.Write("i"); } static void Main() { int i = 7;   Console.Write("i");   teste(); } usando Sistema; programa de classe { int eu; teste de vazio estático () {   i = 2; } static void Main() { teste(); Console.Write("i"); } }

Tarefa
Escreva um procedimento que troque os valores de duas variáveis.

A peculiaridade dessa tarefa é que precisamos que as alterações feitas no procedimento se tornem conhecidas do programa chamador.

Vamos tentar escrever o procedimento assim: static void Swap (int a, int b) // com tal descrição dos parâmetros do procedimento, { // irá copiar os valores dos argumentos (x e y) int c; // variáveis ​​a e b são variáveis ​​independentes não relacionadas a x e y c = a; a = b; b=c; } static void Main() { int x=1, y=2; Trocar(x, y); //valores das variáveis ​​x e y (argumentos) são copiados nos parâmetros a e b, x = 1, y = 2 } Se você executar este programa, poderá ver que os valores das variáveis ​​x e y não foram alterados. Para que os parâmetros alterem os valores dos argumentos, você deve usar dados passando por referência. Para isso, você deve escrever ref antes do nome do tipo de dados no cabeçalho da sub-rotina. void Swap ( ref int a, ref int b ) // agora as variáveis ​​a e b obtêm os endereços das variáveis ​​x e y na memória { int c; c = a; a = b; b=c; } static void Main() {   int x=1, y=2;   Swap(ref x, ref y); Aplicação: se você passar um argumento por referência, então somente o nome da variável (NÃO um número e NÃO uma expressão aritmética) pode ficar neste lugar ao chamar o procedimento.

Você não pode chamar um procedimento como este: Trocar(x, 4); Trocar(5+x, y);