Back-End

19 set, 2016

Dicas da linguagem Visual C# 6

Publicidade

O mundo das linguagens de programação vem crescendo e evoluindo a cada dia. Em algumas, é preciso se dedicar às novidades para deixar os códigos mais limpos e de fácil entendimento, ainda mais quando temos um time de desenvolvimento no mesmo projeto.

O objetivo deste artigo é explorar algumas novidades do Visual C# 6, aplicáveis a qualquer tipo de projeto que a use. Usarei uma Console Application com o Visual Studio 2015 RC 2.

Remover Usings

Toda vez que você necessita utilizar alguma chamada de um namespace no código, normalmente é declarado na lista de Using nas primeiras linhas do código. No entanto, muitas vezes você pode melhorar essa declaração, de forma que o código fique mais legível. Veja no exemplo a seguir que nas duas primeiras linhas são declarados os namespaces com o uso da palavra chave “static”. Isso significa que quando precisar utilizar o Console.Writeline no código, basta usar Writeline, pois ele está declarado numa classe estática. O mesmo ocorre com o uso dos métodos Round (arredondamento de valores), Abs (valor absoluto) e Sqrt (raiz quadrada), os quais pertencem ao System.Math. Como este foi declarado como “static”, basta usar os métodos diretamente.

using static System.Console;
using static System.Math;

namespace LinguagemCS6
{
    class removerUsing
    {
        static void Main(string[] args)
        {
            var anonimo = new { esporte = "kitesurf" };
            WriteLine(anonimo.esporte);

            var valor = 98.543M;
            WriteLine(Round(valor));
            WriteLine(Abs(valor));
            WriteLine(Sqrt(64));
            ReadLine();
        }
    }
}

Sendo assim, você pode desenvolver suas próprias classes, e para utilizar esse recurso é obrigatório que sejam declaradas como classe estática.

Inicializar propriedades

Quantas vezes você teve que inicializar as propriedades diretamente no construtor da classe? Sempre, correto, porém agora com o C# 6 temos um recurso que facilita muito tais declarações. Você não precisa declarar no construtor, e sim na própria declaração da propriedade. No exemplo a seguir, veja a classe produto contendo 5 propriedades, sendo que o nome, o preço e a quantidade contêm dados que serão usados como default das propriedades. Nunca foi tão fácil declarar algo, basta digitar logo após o { get; set;}, de acordo com o tipo de dado da propriedade.

using static System.Console;
using System.Collections.Generic;
using System.Linq;

namespace LinguagemCS6
{
public class produto
{
    public int ID { get; set; }
    public string Nome { get; set; } = "Produto novo";
    public decimal Preco { get; set; } = 8.99M;
    public double Qtde { get; set; } = 10;
    public bool Ativo { get; } = true;
}

Agora vamos criar a classe para consumir a classe produto. Veja que, no Main, temos um objeto do tipo produto contendo apenas o ID e o Nome. No Writeline, há a expressão completa de todas as propriedades a serem mostradas, sendo que para o preço e a quantidade serão usados os valores default.

Em seguida, temos uma lista de produtos, usando Generics, contendo 5 produtos com quase todas as propriedades preenchidas. Há dois produtos que não contêm ou o preço ou a quantidade. Nesse caso, quando forem impressos, serão usados os dados que foram inicializados no default.

Aproveitamos que temos o .ForEach() que dispara uma Action, na qual temos uma expressão que atribui um código que irá imprimir dados dessa coleção. Note que não uso mais o String.Format – isso é coisa superada pelo $”expressão”, que demonstrarei mais adiante no artigo.

class IniciarPropriedades
{
    static void Main(string[] args)
    {
        // criar um objeto
        var prod = new produto
        {
            ID = 1,
            Nome = "Farinha de trigo"
        };

        WriteLine(quot;{prod.ID} - {prod.Nome} preço: {prod.Preco} - qtde: {prod.Qtde}");

        WriteLine("------ listar todos os produtos --------");
        new List<produto>()
        {
            new produto { ID=1, Nome = "Trigo", Preco = 10.9M, Qtde = 8},
            new produto { ID=2, Nome = "Arroz", Preco = 10.75M},
            new produto { ID=3, Nome = "Açúcar", Qtde = 10},
            new produto { ID=4, Nome = "Feijão", Preco = 5.87M, Qtde = 80},
            new produto { ID=5, Nome = "Pimenta", Preco = 14.32M, Qtde = 92}
        }.ToList().ForEach(p =>
          WriteLine(quot;{p.ID} - {p.Nome} preço: {p.Preco} - qtde: {p.Qtde}"));
            
        ReadLine();
    }
}
}

Quando executar esse código, os dados listados serão conforme a figura 1.

im-1Figura 1 – Resultado da listagem

Dicionários de dados

No Visual C# 6, a forma de declarar dicionário de dados mudou – ficou um tanto mais claro o acesso aos índices, a forma de referenciar uma chave e capturar o conteúdo. Veja que na declaração você deve informar o tipo de dado da chave e do conteúdo, por exemplo, Dictionary<string, string> ou Dictionary<int, produto>, ou seja, você pode usar todos os tipos existentes, inclusive suas classes.

Nos exemplos a seguir, o dicionário de sexo tem as chaves M e F, e o acesso a qualquer elemento ocorre por essas chaves – por exemplo, sexo[“F”]. Já no dicionário de cidades, cada estado tem como chave a sigla do estado e o conteúdo, o nome. Em seguida, montei um ForEach para listar todos os itens de cidades, mostrando a chave (key) e o conteúdo (value). No entanto, deixei explícito que se você referenciar uma chave que não existe, gera um erro, afinal a chave “SC” é diferente de “sc” – sim, é Case Sensitive. E também o índice [0] dará erro de compilação, afinal ele não existe, pois o dicionário tem como chave uma String.

Já no exemplo de países, temos como chave um “int”, e somente os números declarados nas chaves é que serão usados. Se você quiser ler a chave países[0] dará erro, pois não existe.

E, para finalizar, temos um dicionário em que a chave é um “int”, e os dados são as propriedades do objeto produto. Nesse caso, veja no WriteLine que o acesso às propriedades ocorre através do Value.Propriedade.

using static System.Console;
using System.Collections.Generic;
using System.Linq;

namespace LinguagemCS6
{
class dicionarios
{
    static void Main(string[] args)
    {
        WriteLine("--- uso de dicionários ---");
        var sexo = new Dictionary<string, string>();
        sexo.Add("M", "Masculino");
        sexo.Add("F", "Feminino");
        WriteLine(sexo["F"]);

        var cidades = new Dictionary<string, string>
        {
            ["SC"] = "Santa Catarina",
            ["SP"] = "São Paulo",
            ["RS"] = "Rio Grande do Sul"
        };
        WriteLine("--- dicionário Cidades ---");
        WriteLine(cidades["SC"]);
        //WriteLine(cidades["sc"]); // gera erro
        //WriteLine(cidades[0]); // erro compilação
        cidades.ToList().ForEach(p => WriteLine(quot;{p.Key} - {p.Value}"));

        WriteLine("--- dicionário Países ---");
        var paises = new Dictionary<int, string>
        {
            [1] = "Brasil",
            [2] = "Australia",
            [3] = "Nova Zelandia"
        };
        paises.ToList().ForEach(p => WriteLine(quot;{p.Key} - {p.Value}"));

        //---------------- dic com classe
        WriteLine("--- dicionário Classes ---");
        new Dictionary<int, produto>
        {
            [1] = new produto { Nome = "mouse", Preco = 25 },
            [2] = new produto { Nome = "ultrabook", Preco = 2500 },
            [5] = new produto { Nome = "impressora", Preco = 500 }
        }.ToList().ForEach(p =>
        WriteLine(quot;índice: {p.Key} - {p.Value.Nome} | preço: {p.Value.Preco}"));

        ReadLine();
    }
}
}

Executando esse código de dicionários, teremos resultados como na figura 2.

im-2Figura 2 – Dicionários de dados

Expression Bodied/Interpolação de String

O C# 6 tem duas features que nos ajudam muito na codificação. A primeira a destacar é o que chamamos de Expression Bodied, ou seja, permite criar métodos com expressões diretamente na declaração de uma classe. Veja a classe carro criada a seguir – temos quatro métodos contendo expressões, pode-se entender cálculos. Por exemplo, o Consumo() retorna um double com a fórmula que divide kmRodados por Litros. O método Idade retorna uma string com a subtração do (ano atual – AnoFabricacao). O consumoString() retorna uma string que contém uma condição, ou seja, se a propriedade Litros for > 0, chama o método Consumo; caso contrário, retorna “—-”. E para finalizar, o ToString() retorna o ID e o Modelo do carro. Veja o quanto que a classe ficou clara de se entender e aplicar.

Já a classe expressionBodied contém uma declaração CalculaPreco, que recebe dois parâmetros (decimal e int, respectivamente), efetua uma expressão (preco * qtde) e retorna um decimal. Dentro do método Main, todos os métodos da classe carro e o CalculaPreco são invocados.

A segunda feature que destaco é a interpolação de String, na qual escrever uma expressão se tornou muito mais simples, claro, objetivo e de fácil manutenção. Você, desenvolvedor, que sempre usou String.Format, deve ter tido, em alguns momentos, erros nas declarações dos parâmetros, pois o índice nem sempre constava nas declarações ou, ainda, referenciava um índice errado. De qualquer forma, o String.Format é sempre melhor que ficar concatenando strings. Agora, o C# 6 permite declarar tudo dentro de uma expressão, ou seja, dentro de aspas você monta a expressão. Toda vez que precisar chamar uma variável, use o {}. O pré-requisito é que a expressão inicie com o símbolo $. Veja a seguir quantas declarações usei. Todas as vezes que quiser formatar um dado, basta utilizar dois pontos seguidos da expressão de formatação, por exemplo, :n2, :c2.

using static System.Console;
using System;

namespace LinguagemCS6
{
class carro
{
    public int ID { get; set; }
    public string Modelo { get; set; }
    public int Litros { get; set; }
    public double KmRodados { get; set; }
    public int AnoFabricacao { get; set; }
    public double Consumo() => KmRodados / Litros;
    public string Idade() => (DateTime.Today.Year - AnoFabricacao).ToString();
    public string ConsumoString() => Litros > 0 ? Consumo().ToString() : "----";
    public override string ToString() => quot;{ID} : {Modelo}";
}

class expressionBodied
{
    public static decimal CalculaPreco(decimal preco, int qtde)
                            => preco * qtde;
    static void Main(string[] args)
    {
        WriteLine(quot;Valor do produto no estoque {CalculaPreco(10,15)}");

        var c = new carro
        {
            ID = 1,
            Modelo = "JEEP",
            AnoFabricacao = 2007,
            KmRodados = 800,
            Litros = 42
        };
        WriteLine(quot;O carro {c.Modelo}, fabricado em {c.AnoFabricacao} está com {c.Idade()} anos.");
        WriteLine(quot;Rodando {c.KmRodados} km com {c.Litros} litros, a média é de {c.Consumo():n2} km/litro.");
        WriteLine(c.ToString());

        var c2 = new carro
        {
            ID = 2,
            Modelo = "Landau",
            AnoFabricacao = 1980,
            KmRodados = 1200,
        };
        WriteLine(quot;Rodando {c2.KmRodados} km com {c2.Litros} litros, a média é de {c2.ConsumoString()} km/litro.");

        ReadLine();
    }
}
}

Execute esse código e verá o resultado como na figura 3.

im-3Figura 3 – Uso de Expression Bodied

Sem dúvida nenhuma que falar sobre codificação é uma tarefa satisfatória para qualquer desenvolvedor. Trocar experiências e códigos, ver como estão aplicando e pensar que tudo pode ser mais fácil é um grande desafio. Fique atento sempre às novidades das linguagens, ferramentas, patterns e se envolva nas comunidades para trocar experiências.

Conclusão

Ver uma linguagem como o C# evoluir tanto para nos auxiliar na codificação é sempre uma forma de melhorar os códigos, compartilhar com outras pessoas o conhecimento e aprender eternamente. Como desafio, pegue um projeto em que você tenha muitas linhas de códigos e tente aplicar o aprendizado deste artigo, assim é que começamos.

Agradeço a oportunidade de poder compartilhar o conhecimento deste artigo. Qualquer dúvida e, necessitando de treinamento, por favor me contate.