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.
Figura 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.
Figura 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.
Figura 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.