Dicas da Linguagem Visual C# 6
O mundo das linguagens de programação vem crescendo e evoluindo a cada dia. Algumas é preciso se dedicar as 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 o 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 esta declaração, de forma que o código fique mais legível. Veja no exemplo a seguir que as duas primeiras linhas são declarados os namespaces com o uso da palavra chave “static”. Isto significa que quando precisar utilizar o Console.Writeline no código, basta usar Writeline, pois o mesmo 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 deste 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 tem a expressão completa de todas as propriedades a serem mostradas, sendo que 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. Neste caso, quando forem impressos, tais dados serão usados os que foram inicializados no default.
Aproveitando que temos o .ForEach() que dispara uma Action, o qual temos uma expressão que atribui um código que irá imprimir dados desta coleção. Note que não uso mais o String.Format, isto é coisa superada pelo $”expressão”, o qual 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($"{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($"{p.ID} - {p.Nome} preço: {p.Preco} - qtde: {p.Qtde}"));
ReadLine();
}
}
}
Quando executar este 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 estas 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á o 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 onde a chave é um “int” e os dados são as propriedades do objeto produto. Neste 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($"{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($"{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($"índice: {p.Key} - {p.Value.Nome} | preço: {p.Value.Preco}"));
ReadLine();
}
}
}
Executando este 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, o 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() => $"{ID} : {Modelo}";
}
class expressionBodied
{
public static decimal CalculaPreco(decimal preco, int qtde)
=> preco * qtde;
static void Main(string[] args)
{
WriteLine($"Valor do produto no estoque {CalculaPreco(10,15)}");
var c = new carro
{
ID = 1,
Modelo = "JEEP",
AnoFabricacao = 2007,
KmRodados = 800,
Litros = 42
};
WriteLine($"O carro {c.Modelo}, fabricado em {c.AnoFabricacao} está com {c.Idade()} anos.");
WriteLine($"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($"Rodando {c2.KmRodados} km com {c2.Litros} litros, a média é de {c2.ConsumoString()} km/litro.");
ReadLine();
}
}
}
Execute este 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 as 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 onde 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.
Sobre o Autor
Renato Haddad (rehaddad@msn.com – www.renatohaddad.com ) é MVP, MS Regional Director, MCPD e MCTS, palestrante em eventos da Microsoft em diversos países, ministra treinamentos focados em produtividade com o VS.NET 2013/2015, ASP.NET Core, 4/5, Power BI, Entity Framework, Reporting Services, Universal Windows Platform. Visite o blog https://weblogs.asp.net/renatohaddad.