Back-End

12 set, 2017

C# 7.0: Tuplas – Como simplificar a manipulação de agrupamentos de dados

Publicidade

C# 7.0: Tuplas

Manipular conjuntos de valores constitui um tipo de ocorrência extremamente comum no desenvolvimento de aplicações, existindo inclusive inúmeras formas de se realizar este tipo de tarefa.

Dentre as abordagens disponíveis é possível destacar:

  • A criação de classes, com propriedades representando cada um dos diferentes elementos que compõem um agrupamento de dados. Em tais situações há uma certa tendência de crescimento desenfreado no número de tipos que integram um projeto, sobretudo se considerarmos o escopo de utilização reduzido para muitas das estruturas geradas (simples retornos de métodos)
  • No caso de específico de métodos, a necessidade de retornar múltiplos valores pode levar ao uso de parâmetros associados aos modificadores out e ref (com a passagem de valores por referência). Embora funcional, a opção frequente por esta prática pode resultar em uma codificação mais extensa e nem sempre tão elegante.
  • Uma alternativa seria a utilização de uma instância baseada em um tipo anônimo, em conjunto com o modificador dynamic. Ao empregar esta técnica o desenvolvedor abrirá mão da checagem estática de tipos. Importante ressaltar que esta solução também acarreta custos adicionais em termos de performance.

 

O C# 7.0 conta agora com as tuplas (em inglês tuples), um novo tipo de estrutura concebido com o intuito de simplificar a manipulação de agrupamentos de dados nos cenários aqui descritos. Para ativar este recurso será necessário adicionar o package System.ValueTuple a um projeto:

C# 7.0: Tuplas

A próxima listagem possui 3 exemplos envolvendo o uso de tuplas:

  • Uma tupla pode ser formada por 1, 2, 3 ou mais itens, com os tipos de suas diferentes propriedades e seus respectivos valores sendo declarados entre parênteses;
  • As tuplas parValores e dezenas contam com campos cujo nomes não foram declarados explicitamente. Por convenção, serão assumidos como identificadores Item1, Item2, Item3 e assim por diante (levando em conta a ordem de declaração e a quantidade de elementos presentes);
  • Já a tupla coordenadas foi declarada empregando o modificador var. Os nomes de suas diferentes propriedades também foram especificados, de forma a facilitar o acesso aos dados que as mesmas representam.

 

using System;
namespace ExemploTuplas01
 {
 class Program
 {
 static void Main(string[] args)
 {
 (int, int) parValores = (7, 49);
 Console.WriteLine(quot;Valor = {parValores.Item1} ----- " +
 quot;Quadrado = {parValores.Item2}");
(int, int, int) dezenas = (10, 20, 30);
 Console.WriteLine(quot;Valor 1 = {dezenas.Item1} ----- " +
 quot;Valor 2 = {dezenas.Item2} ----- " +
 quot;Valor 3 = {dezenas.Item3}");
var coordenadas = (latitude: "23.5505° S", longitude: "46.6333° W");
 Console.WriteLine(quot;São Paulo - " +
 quot;Latitude = {coordenadas.latitude} - " +
 quot;Longitude = {coordenadas.longitude}");
Console.ReadKey();
 }
 }
 }

Uma das grandes vantagens do uso de tuplas, quando comparadas a referências dinâmicas, está no suporte do IntelliSense a esse novo tipo de recurso. Isto pode ser observado na imagem a seguir:

C# 7.0: Tuplas

A execução deste conjunto de instruções produzirá o seguinte resultado:

C# 7.0: Tuplas

A tendência é que tuplas sejam utilizadas como retorno de métodos, como no caso da operação ConverterTemperaturas (cuja implementação está na listagem a seguir):

  • O retorno de ConverterTemperaturas pode ser associado a uma referência declarada com o modificador var, conforme indicado na declaração da variável resultado1;
  • É possível também consumir resultados baseados em tuplas através de uma técnica conhecida como desconstrução (deconstruction), como especificado nos outros 3 exemplos de uso do método ConverterTemperaturas;
  • A declaração das variáveis resFahrenheit2, resCelsius2 e resKelvin2 entre parênteses permitirá que os valores da tupla produzida ao invocar ConverterTemperaturas sejam associados a estas referências;
  • O segundo exemplo de desconstrução é bastante similar ao primeiro, exceto pela presença de um discard representado pelo caracter “_” (underline). Este ajuste dispensa a declaração de uma variável que receberia o valor armazenado pela propriedade tempFahrenheit da tupla;
  • No terceiro caso de desconstrução as variáveis resFahrenheit4, resCelsius4 e resKelvin4 foram declaradas da forma convencional e, num segundo momento, associadas em sequência ao retorno do método ConverterTemperaturas.

 

using System;
namespace ExemploTuplas02
 {
 class Program
 {
 private static (double tempFahrenheit, double tempCelsius, double tempKelvin)
 ConverterTemperaturas(double valorFahrenheit)
 {
 double retCelsius = Math.Round((valorFahrenheit - 32) / 1.8, 2);
 double retKelvin = retCelsius + +273.15;
return (valorFahrenheit, retCelsius, retKelvin);
 }
static void Main(string[] args)
 {
 Console.WriteLine("Conversão de temperaturas");
// Exemplo simples
 var resultado1 = ConverterTemperaturas(86);
 Console.WriteLine(quot;Fahrenheit = {resultado1.tempFahrenheit} - " +
 quot;Celsius = {resultado1.tempCelsius} - " +
 quot;Kelvin = {resultado1.tempKelvin}");
// Exemplo 1 - Desconstrução
 (double resFahrenheit2, double resCelsius2, double resKelvin2) =
 ConverterTemperaturas(32);
 Console.WriteLine(quot;Fahrenheit = {resFahrenheit2} - " +
 quot;Celsius = {resCelsius2} - " +
 quot;Kelvin = {resKelvin2}");
// Exemplo 2 - Desconstrução
 double valorFahrenheit3 = 212;
 (_, double resCelsius3, double resKelvin3) =
 ConverterTemperaturas(valorFahrenheit3);
 Console.WriteLine(quot;Fahrenheit = {valorFahrenheit3} - " +
 quot;Celsius = {resCelsius3} - " +
 quot;Kelvin = {resKelvin3}");
// Exemplo 3 - Desconstrução
 double resFahrenheit4;
 double resCelsius4;
 double resKelvin4;
 (resFahrenheit4, resCelsius4, resKelvin4) =
 ConverterTemperaturas(86);
 Console.WriteLine(quot;Fahrenheit = {resFahrenheit4} - " +
 quot;Celsius = {resCelsius4} - " +
 quot;Kelvin = {resKelvin4}");
Console.ReadKey();
 }
 }
 }

O resultado ao processar este conjunto de instruções pode ser observado na próxima imagem:

C# 7.0: Tuplas

E para finalizar, gostaria de saber mais sobre as novidades do C# 7.0? Não deixem de assistir então a gravação de um hangout realizado recentemente pelo Canal .NET sobre este assunto:

Disponibilizei também no GitHub os diferentes exemplos apresentados durante a transmissão:

https://github.com/renatogroffe/CSharp7_VS2017

Referências