Aprenda C#

  • Página Inicial
  • Contato!
  • Tudo sobre C# Parte 1!
  • Tudo sobre C# Parte 2!
  • Tudo sobre C# Parte 3!
  • Tudo sobre C# Parte 4!
  • Tudo sobre C# Parte 5!
  • Tudo sobre C# Parte 6!
  • Tudo sobre C# Parte 7!
  • Tudo sobre C# Parte 8!
  • Tudo sobre C# Parte 9!
  • Tudo sobre C# Parte 10!
  • Tudo sobre C# Parte 5

    Arrays - Copiando e Clonando

    Para copiarmos os dados de um array, vamos proceder da seguinte forma: Criamos uma nova instância de array do mesmo tipo e mesmo tamanho do array original. Depois, copiamos os elementos um por um do original para o novo array.

    Veja abaixo um exemplo:

    
    using System;
    
    namespace ArraysCopiandoEClonando {
        class Program {
            static void Main(string[] args) {
                int[] numeros = {4, 8, 12, 16, 20};
                int[] copia = new int[numeros.Length];
    
                for(int i = 0; i < numeros.Length; i++) {
                    copia[i] = numeros[i];
                }
    
                for(int i = 0; i < numeros.Length; i++) {
                    Console.WriteLine(copia[i]);
                }
    
                Console.Read();
            }
        }
    }
    
    

    Como copiar elementos do array é algo comum em programação, o C# possuí um método próprio para isso, o CopyTo(), usado dessa forma:

    
    using System;
    
    namespace ArraysCopiandoEClonando {
        class Program {
            static void Main(string[] args) {
                int[] numeros = {4, 8, 12, 16, 20};
                int[] copia = new int[numeros.Length];
    
                numeros.CopyTo(copia, 0);
    
                for(int i = 0; i < copia.Length; i++) {
                    Console.WriteLine(copia[i]);
                }
    
                Console.Read();
            }
        }
    }
    
    

    PS: O CopyTo também pode copiar trechos de array, para colocar em outro array menor.

    Também podemos usar o método Copy da classe Array, assim:

    
    int[] numeros = {4, 8, 12, 16, 20};
    int[] copia = new int[numeros.Length];
    
    Array.Copy(numeros, copia, copia.Length);
    
    for(int i = 0; i < copia.Length; i++) {
        Console.WriteLine(copia[i]);
    }
    
    

    E podemos clonar ele também, diretamente, usando o método Clone(), dessa forma:

    
    int[] numeros = {4, 8, 12, 16, 20};
    int[] copia = (int[])numeros.Clone(); // Não esquecer do typecast
    
    for(int i = 0; i < copia.Length; i++) {
        Console.WriteLine(copia[i]);
    }
    
    

    Listas em C#

    Os arrays em C# tem um problema, sempre terão posições fixas, caso necessitemos de uma variável composta com valores variáveis, utilizamos a lista, que é declarada assim:

    
    List<int> numeros = new List<int>(); // inclua System.Collections.Generic
    
    

    PS: A declaração pode ser com a interface IList (mas esta não permitirá trabalhar com alguns métodos), a inicialização é List mesmo.

    Dentro das tags sempre irão o tipo primitivo ou classe invólucro dos elementos a serem colocados na lista. Para exibir os índices usamos as posições igual num array comum (como numeros[0]).

    Para adicionar elementos à lista, usamos o método Add(), veja um exemplo no qual preenchemos a lista através de um laço while:

    
    List<int> numeros = new List<int>();
    int num = 1;
    
    while(num <= 10) {
        numeros.Add(num);
        num++;
    }
    
    for(int i = 0; i < numeros.Count; i++) {
        Console.WriteLine(numeros[i]);
    }
    
    

    Exemplo mais comum de inicialização:

    
    List<int> numeros = new List<int>();
    
    numeros.Add(5);
    numeros.Add(10);
    
    

    Forma simplificada:

    
    List<int> numeros = new List<int> {
        5,
        10
    };
    
    

    Para remover elementos da lista, usamos o Remove() (para remover pelo conteúdo), ou o RemoveAt() (que remove pelo índice). O Clear() limpa toda a lista e o Any() verifica se ela tem itens:

    
    numeros.Remove(10); // Remove pelo conteúdo
    
    numeros.RemoveAt(0); // Remove pelo índice
    
    numeros.Clear(); // Remove tudo
    
    numeros.Any(); // Verifica se tem itens e retorna um booleano
    
    

    Para vermos se existe um elemento dentro da lista, usamos o Contains(), assim:

    
    Console.WriteLine(numeros.Contains(15));
    
    

    Para vermos a quantidade de elementos de uma lista, usamos o Count, assim:

    
    Console.WriteLine(numeros.Count);
    
    

    Para ordenar os elementos da lista, usamos o Sort() assim:

    
    numeros.Sort(); // Não use com IList, e sim com List na inicialização.
    
    

    E para exibir invertido, podemos usar ele em conjunto com o Reverse(), assim:

    
    numeros.Sort(); // Não use com IList, e sim com List na inicialização.
    
    numeros.Reverse(); // Idem.
    
    

    Para exibir os elementos da lista, podemos usar o foreach, dessa forma:

    
    foreach(int n in numeros) {
        Console.WriteLine(n);
    }
    
    

    Podemos usar uma Lambda para iterar a list, assim:

    
    numeros.ForEach((n) => { // Não use IList com lambdas.
        Console.WriteLine(n);
    });
    
    

    Se for tudo na mesma linha, podemos simplificar mais, tirando as chaves:

    
    numeros.ForEach(n => Console.WriteLine(n));
    
    

    Métodos - Declarando e Invocando

    Um método é uma sequência de declarações (comandos) que possui um nome de identificação. É similar a uma função ou procedimento. Um método possui um nome e um corpo onde ficam os comandos que serão executados quanto o método for chamado. Os métodos também podem receber dados para processamento (parâmetros) e retornar informações.

    Os métodos em C#, assim como em outras linguagens fortemente tipadas, você coloca o tipo de retorno nele, por exemplo, int ou string. Caso você esteja escrevendo um método que não retornará um valor, use a palavra void no lugar do tipo de retorno.

    O próprio método Main, é o método principal onde nosso programa é executado, todo programa em C# tem que ter esse método dentro da classe principal. Os métodos que criarmos são criados fora do Main (normalmente, nenhum método se cria dentro de outro), e invocados dentro dele. Deverá ter também a indicação static antes, que mostrará um método estático.

    Veja um exemplo de criação de métodos, onde passamos parâmetros para ele, e ele retorna valores:

    
    using System;
    
    namespace MetodosDeclarandoEInvocando {
        class Program {
            static void Main(string[] args) {
                int adicao;
                int valor1, valor2;
    
                Console.Write("Digite um número: ");
                valor1 = int.Parse(Console.ReadLine());
                Console.Write("Digite um número: ");
                valor2 = int.Parse(Console.ReadLine());
    
                adicao = soma(valor1, valor2);
    
                Console.WriteLine("A soma é {0}.", adicao.ToString());
    
                Console.Read();
            }
    
            static int soma(int n1, int n2) {
                int resul = n1 + n2;
    
                return resul;
            }
        }
    }
    
    

    PS: Os parâmetros não são obrigatórios ter em todas as funções, mas caso tenham, tem que ser passados todos eles nas invocações, no entanto, podemos inicializar esses mesmos parâmetros com valores padrão, mas não é recomendado usar porque é melhor usar a sobrecarga, que veremos mais pra frente. E tem casos que a declaração static não é obrigatória num método. Nos casos acima, é devido ao método main ser estático, e por isso só pode trabalhar com métodos estáticos.

    Métodos - Parâmetros de Valor

    Em C# temos quatro tipos de parâmetros de métodos, valor, ref, out e params.

    O parâmetro de valor é o tipo padrão. Os parâmetros de valor passam uma cópia local de si mesmos ao método. Ou seja, o método usa o parâmetro, porém a cópia original do chamador não é modificada. O Argument opassado deve ser do mesmo tipo do parâmetro, ou ao menos conversível implicitamente.

    Veja um exemplo simples de parâmetros de valor:

    
    using System;
    
    namespace MetodosParametrosDeValor {
        class Program {
            static void Main(string[] args) {
                int numero;
    
                Console.Write("Digite um número: ");
                numero = int.Parse(Console.ReadLine());
    
                quadrado(numero);
    
                Console.WriteLine("O número digitado foi {0}.", numero.ToString());
    
                Console.Readline();
            }
    
            static void quadrado(int num) {
                int quad = num * num;
    
                Console.WriteLine("O quadrado de {0} é {1}.", num, quad.ToString());
            }
        }
    }
    
    

    PS: Nos parâmetros também podemos passar arrays, passando a variável com colchetes, algo tipo funcao(int[] vetorpassado).

    Métodos - Parâmetros ref

    Prefixando um parâmetro com a palavra ref, o compilador do C# gera código que passa uma referência ao argumento real em vez de uma cópia do argumento.Tanto o argumento quanto o parâmetro referenciam os mesmos dados.

    Veja um exemplo logo abaixo, onde usamos ref antes do tipo do parâmetro:

    
    using System;
    
    namespace MetodosParametrosRef {
        class Program {
            static void Main(string[] args) {
                int numero;
    
                Console.Write("Digite um número: ");
                numero = int.Parse(Console.ReadLine());
    
                incrementa(ref numero); // Passa a referência na invocação
    
                Console.WriteLine("O valor incrementado é {0}.", numero);
    
                Console.Read();
            }
    
            static void incrementa(ref int valor) { // Indica a referência aqui também.
                valor++;
            }
        }
    }
    
    

    No caso, o ref não copia o valor da variável, e sim pega o endereço da posição do argumento (referência do local onde o argumento está).

    Da forma acima, a variável número também é incrementa, junto com a valor.

    Métodos - Sobrecarga

    Métodos sobrecarregados são métodos que possuem o mesmo nome e são declarados no mesmo escopo. A sobrecarga é útil quanto precisamos efetuar a operação em tipos diferentes de dados ou conjuntos de informações que variam. Métodos sobrecarregados podem possuir números de parâmetros diferentes ou ainda tipos de parâmetros diferentes. O tipo de dados de retorno, contudo, é sempre o mesmo para todos os métodos sobrecarregados. Um exemplo clássico é o método Writeline() da classe Console.

    Veja abaixo um exemplo, onde temos duas funções com mesmo nome, diferenciadas pelos parâmetros passados nas mesmas:

    
    using System;
    
    namespace MetodosSobrecarga {
        class Program {
            static void Main(string[] args) {
                double resultado;
                int num1, num2;
    
                Console.Write("Digite um Nº para calcular seu quadrado: ");
                num1 = int.Parse(Console.ReadLine());
    
                resultado = potencia(num1);
    
                Console.WriteLine("O quadrado de {0} é {1}.", num1, resultado);
    
                Console.WriteLine();
    
                Console.Write("Digite dois Nº para calcular x ^ y: ");
                num1 = int.Parse(Console.ReadLine());
                num2 = int.Parse(Console.ReadLine());
    
                resultado = potencia(num1, num2);
    
                Console.WriteLine("{0} elevado a {1} é {2}.", num1, num2, resultado);
    
                Console.Read();
            }
    
            static double potencia(int valor1) {
                return valor1 * valor1;
            }
    
            static double potencia(int valor1, int valor2) {
                return Math.Pow(valor1, valor2);
            }
        }
    }
    
    

    No caso acima, o programa identificará qual é o método invocado pelo parâmetros. O próprio Console.WriteLine() trabalha com sobrecarga, pois quando usamos ele de forma formatada, ele recebe alguns parâmetros, além da string.

    Expressões Lambdas

    As expressões lambda se comportam como um tipo de delegate. Entendemos que a expressão lambda é uma espécie de função, porém sem nome, elas realizam cálculos, filtros, e retornam um valor (ou uma coleção de valores).

    Para criar uma expressão lambda simples, basta declarar ela assim:

    
    Action expr = () => {
        Console.WriteLine("Exibição de Lambda!");
    };
    
    expr(); // Invocando a expressão lambda.
    
    

    Podendo inclusive, se for na mesma linha, omitir as chaves, assim:

    
    Action expr = () => Console.WriteLine("Exibição de Lambda!");
    
    expr();
    
    

    Caso necessite criar uma função que retorne um valor e/ou precise de parâmetros, crie uma função abstrata indicando delegate, por exemplo:

    
    delegate int Resul(int n1, int n2); // Método abstrato que retornará um valor
        
    static void Main(string[] args) {  
        Resul soma = (n1, n2) => n1 + n2; // Note que indicar retorno e tipos é desnecessário
    
        Console.WriteLine(soma(10, 5));
    }
    
    

    Também podemos usar Lambdas para correr elementos de um contâiner, por exemplo:

    
    List<string> bebidas = new List<string>(); // Não use IList
                
    bebidas.Add("Água");
    bebidas.Add("Suco");
    bebidas.Add("Refrigerante");
    
    // Ambos abaixo substituem o foreach tradicional:
    
    // Sem Lambda:
    bebidas.ForEach(delegate(string b) {
        Console.WriteLine(b);
    });
    
    // Com Lambda:       
    bebidas.ForEach(b => Console.WriteLine(b));