.NET - Apresentando Tuples


O conceito de tuplas não é novo no desenvolvimento de sistemas estando mais vinculado a banco de dados, onde cada linha formada por uma lista ordenada de colunas representa um registro, ou tupla.(Phyton, F# são linguagens que usam o conceito de tuplas)

Cada linha formada por uma lista ordenada de colunas representa um registro, ou tupla. Os registros não precisam conter informações em todas as colunas, podendo assumir valores nulos quando assim se fizer necessário. http://pt.wikipedia.org/wiki/Banco_de_dados_relacional#Registros

A partir da versão do .NET Framework temos a nossa disposição um novo conjunto de classes que podem ser usadas para realizar o tratamento de um conjunto de elementos tipados distintos. Eles são chamados tuples e possuem as seguintes assinaturas:

public class Tuple <T1>
public class Tuple <T1, T2>
public class Tuple <T1, T2, T3>
public class Tuple <T1, T2, T3, T4>
public class Tuple <T1, T2, T3, T4, T5>
public class Tuple <T1, T2, T3, T4, T5, T6>
public class Tuple <T1, T2, T3, T4, T5, T6, T7>
public class Tuple <T1, T2, T3, T4, T5, T6, T7, TRest>
Public Sub New ( item1 As T1, _
		       item2 As T2, _
	     	       item3 As T3, _
	     	       item4 As T4, _
		        item5 As T5, _
       	     	        item6 As T6, _
	            	        item7 As T7, _
	     	        rest As TRest _
                       )
C #
 VB .NET

Cada uma delas possui propriedades somente-leitura chamadas item1, item2, etc., uma para cada tipo de parâmetro.

Assim, basicamente a classe Tuple() fornece métodos estáticos para criar objetos de coleção de itens.

Uma tupla é uma estrutura de dados que tem um número específico e sequencial de elementos. Um exemplo de uma tupla é uma estrutura de dados com três elementos (conhecido como uma tupla de 3 ou o triplo) que é usada para armazenar um identificador, como o nome da pessoa no primeiro elemento, um ano no segundo elemento e a renda da pessoa no terceiro elemento.

A plataforma .NET da suporta diretamente tuplas com um até sete elementos; além disso, você pode criar tuplas de oito ou mais elementos pelo aninhamento de objetos de coleção de itens na propriedade Rest de um objeto :

Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>        Public Sub New ( item1 As T1,item2 As T2, item3 As T3, item4 As T4, item5 As T5, item6 As T6, item7 As T7, rest As TRest )
C#	
 VB .NET

Você pode instanciar uma tupla via construtor:

var t = new Tuple<int,string> (123, "Macoratti");    	
Dim t = New Tuple(Of Integer, String)(123, "Macoratti")	

C#

VB .NET

ou via método estático :

Tuple<int,string> t = Tuple.Create (123, "Macoratti");   
 Dim t As Tuple(Of Integer, String) = Tuple.Create(123, "Macoratti")	

C#

VB .NET

Neste caso temos um caso de inferência implícita que você pode também declarar da seguinte forma:

  var t = Tuple.Create (123, "Macoratti");  
   Dim t = Tuple.Create(123, "Macoratti")

C#

VB .NET

Para acessar as propriedades você pode fazer da seguinte forma (note que cada uma delas é estaticamente tipada):

static void Main(string[] args)
{
  var t = new Tuple<int, string>(123, "Macoratti");
  Console.WriteLine(t.Item1 * 2);             
// 246
  Console.WriteLine(t.Item2.ToUpper());  
// MACORATTI

  Console.ReadKey();
}
Sub Main()
   Dim t = New Tuple(Of Integer, String)(123, "Macoratti")
   Console.WriteLine(t.Item1 * 2)
   Console.WriteLine(t.Item2.ToUpper())
   Console.ReadKey()
End Sub
C# VB .NET

As Tuplas são convenientes para retornar mais de um valor a partir de um método ou na criação de coleção de pares de valores.

Uma alternativa para as tuplas é a utilização de uma matriz de objetos. Mas neste caso você perde a tipagem estática segura, além de ter que arcar com os custos de realizar o boxing/unboxing para os tipos de valor, que exigem a realização da conversão forçada que não podem ser validadas pelo compilador. O mesmo exemplo acima ficaria assim:

 static void Main(string[] args)
 {
        object[] items = { 123, "Macoratti" };
        Console.WriteLine(((int)items[0]) * 2);                 // 246
        Console.WriteLine(((string)items[1]).ToUpper());  // MACORATTI
        Console.ReadKey();
}
Sub Main()
   Dim items As Object() = {123, "Macoratti"}
   Console.WriteLine(CInt(items(0)) * 2)
   Console.WriteLine(DirectCast(items(1), String).ToUpper())
   Console.ReadKey()
End Sub
C# VB .NET

Tuplas em geral são usadas de quatro maneiras:

A classe Tuple não representa ela mesma uma tupla, em vez disso, ela é uma classe factory que fornece métodos estáticos para criar instâncias dos tipos de coleção de itens que são suportados pelo .NET Framework. Ela fornece os métodos auxiliares que podem ser chamados para instanciar objetos de coleção de itens sem ter que especificar explicitamente o tipo de cada componente da tupla.

O exemplo a seguir usa o construtor de classe para criar uma tupla de 7 ou septuple que contém dados de população para o Brasil para os censos de 1960,1970,1980,1990, 2000 e 2010:

var populacao = new Tuple<string, int, int, int, int, int, int>("Brasil", 70992343, 94508583, 121150573, 146917459, 169590693,190755799); 
C#

Dim populacao = New Tuple(Of String, Integer, Integer, Integer, Integer, Integer, Integer)("Brasil", 70992343, 94508583, 121150573, 146917459, 169590693,190755799)

VB .NET

Neste outro exemplo criamos uma tupla de 8 (octuple) contendo os números primos menor que 20:

var primos= Tuple.Create(2, 3, 5, 7, 11, 13, 17, 19); Dim primos = Tuple.Create(2, 3, 5, 7, 11, 13, 17, 19)
C# VB .NET

Comparando Tuplas

As Tuplas são classes (e, portanto, tipos de referência) dessa forma ao comparar duas instâncias distintas, com o operador de igualdade (==) você irá obter false. No entanto, o método Equals é sobrescrito para comparar cada elemento individual em vez:

 static void Main(string[] args)
 {
            var t1 = Tuple.Create(123, "Macoratti");
            var t2 = Tuple.Create(123, "Macoratti");
            Console.WriteLine(t1 == t2);             // False
            Console.WriteLine(t1.Equals(t2));      // True
            Console.ReadKey();
}
  Private Sub Main(args As String())
	Dim t1 = Tuple.Create(123, "Macoratti")
	Dim t2 = Tuple.Create(123, "Macoratti")
	Console.WriteLine(t1 = t2) 	            ' False
	Console.WriteLine(t1.Equals(t2))     ' True
	Console.ReadKey()
  End Sub
C# VB .NET

Acessando dados de uma Tupla

Os valores de dados fornecidos para os objetos de tupla são expostos como Item1, Item2, etc . Abaixo temos um exemplo que demonstra como acessar os dados do objeto de tupla.

 class Program
    {
        static void Main(string[] args)
        {
            var t = GetFuncionarioObjetoTupla();
            Console.WriteLine("Nome  : {0} {1}", t.Item1, t.Item2); 
            Console.WriteLine("Idade : {0}", t.Item3);
            Console.WriteLine("Cargo : {0}", t.Item4);
        }

        private static Tuple<string, string, int, string> GetFuncionarioObjetoTupla()
        {
            return new Tuple<string, string, int, string>("Jose Carlos", "Macoratti", 45, "Programador Analista");
        }
    }

   Sub Main()
        Dim t = GetFuncionarioObjetoTupla()
        Console.WriteLine("Nome  : {0} {1}", t.Item1, t.Item2)
        Console.WriteLine("Idade  : {0}", t.Item3)
        Console.WriteLine("Cargo  : {0}", t.Item4)
        Console.ReadKey()
    End Sub

    Private Function GetFuncionarioObjetoTupla() As Tuple(Of String, String, Integer, String)
        Return New Tuple(Of String, String, Integer, String)("Jose Carlos", "Macoratti", 45, "Programador Analista")
    End Function

Aninhando Tuplas

Podemos aninhar tuplas facilmente conforme o exemplo mostrado a seguir:

   class Program
    {
        static void Main(string[] args)
        {
             var t1 = Tuple.Create(1, 2, 3, 4, 5, 6, 7, new Tuple<int, int>(8, 9));
             var t2 = Tuple.Create("Macoratti", 45, new Tuple<string, string>("DF", "Brasilia"));
             Console.WriteLine("Tuple com 8 elementos t1 = :" + t1);
             Console.WriteLine("Tuple com 3 elementos t2 = :" + t2);
             Console.WriteLine(t2.Item1);
             Console.WriteLine(t2.Item2);
             Console.WriteLine(t2.Item3);
             Console.ReadKey();
        }
    }
   Sub Main()
        Dim t1 = Tuple.Create(1, 2, 3, 4, 5, 6, 7, New Tuple(Of Integer, Integer)(8, 9))
        Dim t2 = Tuple.Create("Macoratti", 45, New Tuple(Of String, String)("DF", "Brasilia"))
        Console.WriteLine("Tuple com 8 elementos t1 = :" & Convert.ToString(t1))
        Console.WriteLine("Tuple com 3 elementos t2 = :" & Convert.ToString(t2))
        Console.WriteLine(t2.Item1)
        Console.WriteLine(t2.Item2)
        Console.WriteLine(t2.Item3)
        Console.ReadKey()
    End Sub

Desvantagem das Tuplas

Nem tudo são flores, e existem algumas desvantagens inerentes às tuplas:

1Ts 4:7 Porque Deus não nos chamou para a imundícia, mas para a santificação.

Referências:


José Carlos Macoratti