13,090,541 members (63,807 online)
alternative version

Stats

180.4K views
99 bookmarked
Posted 9 May 2011

C# 4 - Tuples

, 9 May 2011
 Rate this:
Tuples can be very handy for developers, allowing them to return multiple values from a function, the creation of composite keys to Dictionaries and eliminates structs or classes just to fill combobox.

Introduction

Basically, a tuple (Tuple in C#) is an ordered sequence, immutable, fixed-size and of heterogeneous objects, i.e., each object being of a specific type.

The tuples are not new in programming. They are already used in F#, Python and databases. However, they are new to C#. The tuples were introduced in C# 4.0 with dynamic programming.

Background

A) "Each line that consists of an ordered list of columns is a record or tuple. The records may not contain information on all columns, and may take `null `values when this becomes necessary."

Example

`Insert Into Tb_clients values (1,’Frederico’, ‘1975-03-24’)`

In this example, (`1,’Frederico’, ‘1975-03-24’`) is a tuple.

B) “A tuple, in mathematics, is a fixed-size ordered sequence of objects”

http://es.wikipedia.org/wiki/Tuple

Example: In the equation, `2x2 - 4x - 3`, the sequence `(2, -4, -3)` is a tuple.

C) "An enupla (also known as n-tuple) is an ordered sequence of n elements, which can be defined by the ordered pair of recursion.

The main properties that distinguish an enupla are:

• An enupla can contain an object more than once.
• Objects are necessarily represented in the given order. "

http://pt.wikipedia.org/wiki/Tuple

Tuples in .NET 4.0

While anonymous types have similar functionality in C#, they cannot be used as return of methods, as can the type Tuple.

The `KeyValuePair<TKey, TValue>` can be compared to a `tuple<T1, T2>`, a significant difference is that `KeyValuePair `is a `struct `and a `Tuple `is a `class`.

A tuple is an ordered sequence, immutable, fixed size of heterogeneous objects.

 Ordered sequence: The order of items in a tuple follows the order used at the time of its creation. Immutable: All properties are read-only tuple, i.e., once created, it cannot be changed. Fixed Size: The size is set at the time of its creation. If it was created with three items, you cannot add new items. Of heterogeneous objects: Each item has a specific and independent of the type of the other item.

As Tuples don’t have an explicit semantic meaning, your code becomes unreadable.

Creating Tuples

In C#, `Tuple `is a `static `class that implements the "Factory" Pattern to create instances of Tuples. We can create an instance of a Tuple using the constructor or the `static `method "`Create`".

The `static `method "`Create`" that returns an instance of type `Tuple `has eight overloads:

 Overload Description Create 1-tuple, or singleton. Create 2-tuple, or pair. Create 3-tuple, or triple. Create 4-tuple, or quadruple. Create 5-tuple, or quintuple. Create 6-tuple, or sextuple. Create 7-tuple, or septuple. Create 8-tuple, or octuple.

Example

```Tuple<int, string, DateTime> _cliente =
Tuple.Create(1, "Frederico", new DateTime(1975, 3,24)); ```

Tuples have a limit of 8 items. If you want to create a tuple with more items, we have to create nested Tuples.

The eighth item of the tuple has necessarily to be another Tuple. The example below will generate an exception.

```// Error: The eighth element must be a tuple.
var t8 = new Tuple<int,int,int,int,int,int,int,int>(1, 2, 3, 4, 5, 6, 7, 8);  ```

To create a tuple with 8 items, we must do the following:

```var t8 = new Tuple<int,int,int,int,int,int,int,Tuple<int>>
(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8));
var Item8 = t8.Rest.Item1; ```

To create a tuple with more than 8 items, we do as follows:

```var t12 = new Tuple<int,int,int,int,int,int,int,Tuple<int,int,int,int, int>>
(1, 2, 3, 4, 5, 6, 7, new Tuple<int,int,int, int,int>(8,9,10, 11, 12));
<>var Item10 = t12.Rest.Item3;```

What Does A Tuple Represent?

Tuples do not have names that may have some significance. The attributes of a tuple are called "`Item1`", "`Item2`", and so on.

Two Tuples can be equal, but that doesn’t mean they are the same. Its meaning is not explicit, which can make your code less readable. For example, the following two tuples are equal, but represent different things:

(3, 9): Product Code 3 and Quantity 9
(3, 9): 3 and 9 are the codes of clients returned by a query.

As seen above, the fact that a tuple doesn’t carry information about its meaning, its use is generic and the developer decides what it will mean at the time of its creation and use.

So, Why Should We Use Them?

A) Return of Methods

Tuples provide a quick way to group multiple values into a single result, which can be very useful when used as a return of function, without the need to create parameters "`ref`" and `/` or "`out `".

Example

```using System;
namespace TuplesConsoleTest
{
class Program
{
static void Main(string[] args)
{
var _cliente1 = RetornaCliente();
Console.WriteLine("O código do usuário1 é: {0}", _cliente1.Item1);
Console.WriteLine("O Nome do usuário1 é: {0}", _cliente1.Item2);
Console.WriteLine("A data de nascimento do usuário1 é: {0}",
_cliente1.Item3.ToString("dd/MM/yyyy"));
}
static Tuple<int, string, DateTime> RetornaCliente()
{
Tuple<int, string, DateTime> _cliente =
Tuple.Create(1, "Frederico", new DateTime(1975, 3, 24));
return _cliente;
}
}
}```

Another example of methods return is when we must return a list of an anonymous type. In this case, we can easily replace this type by tuples.

Example

```using System;
using System.Collections.Generic;
using System.Linq;
namespace TuplesConsoleTest
{
class Program
{
static List<Tuple<int, string, string, DateTime>> lista;
static void Main(string[] args)
{
CarregaLista();
var result = SelecionaCLientes("M");
foreach (var r in result)
{
Console.WriteLine("Cliente: {0} \t Nome: {1}", r.Item1, r.Item2);
}
}
private static void CarregaLista()
{
lista = new List<Tuple<int, string, string, DateTime>>();
(0, "", "", DateTime.MinValue));
(1, "Fred", "M", new DateTime(1975, 3, 24)));
(2, "Rubia", "F", new DateTime(1983, 12, 17)));
(3, "João", "M", new DateTime(2004, 4, 16)));
(4, "Tatá", "F", new DateTime(1999, 7, 14)));
}
private static IEnumerable<Tuple<int, string>> SelecionaCLientes(string sex)
{
var ret = from t in lista
where t.Item3 == sex
select new Tuple<int, string>(t.Item1, t.Item2);
return ret;
}
}
} ```

B) Composite Key in a Dictionary

Due to the interface `IEquatable `defines `GetHashCode()`, the implementation of the interface `IStructuralEquatable `creates a Hash code combining the members Hash codes, allowing the use of tuples as a composite key for a collection of type `Dictionary`.

Example

```using System;
using System.Collections.Generic;
namespace TuplesConsoleTest
{
class Program
{
static void Main(string[] args)
{
var lista = ListaClienteConta();
var chave = Tuple.Create(1, 1);
lista[chave].Saldo.ToString());

}

public static Dictionary<Tuple<int, int>, ClienteConta> ListaClienteConta()
{
Dictionary<Tuple<int, int>, ClienteConta> lista =
new Dictionary<Tuple<int, int>, ClienteConta>();
ClienteConta cc1 = new ClienteConta(){
Codigo_Cliente = 1,
Codigo_Conta = 1,
Saldo = 525.00 };
ClienteConta cc2 = new ClienteConta(){
Codigo_Cliente = 1,
Codigo_Conta = 2,
Saldo = 765.00 };
return lista;
}
}
public class ClienteConta
{
public int Codigo_Cliente { get; set; }
public int Codigo_Conta { get; set; }
public double Saldo { get; set; }
}
} ```

C) Replace Classes or Structs that are Created Just to Carry a Return or to Fill a List

Using the Tuple, we don’t need to create classes or structures to store only temporary values, such as creating a struct or class to add values to a `combobox `or `listbox`. With the tuples, it will no longer be necessary to create them.

Example

```using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace TuplesTest
{
public partial class Form1 : Form
{
List<Tuple<int, string>> lista = new List<Tuple<int, string>>();
public Form1()
{
InitializeComponent();
}
{
var lstOrdenada = lista.OrderBy(t => t.Item2).Select(t=>t).ToList();
}
{
var lstOrdenada = lista.OrderBy(t => t.Item1).Select(t => t).ToList();
}
private void btnOK_Click(object sender, EventArgs e)
{
if (rbtNome.Checked)
else
lstNomes.ValueMember = "Item1";
lstNomes.DisplayMember = "Item2";
}
}
} ```

Comparing and Ordering

The interfaces `IStructuralComparable `and `IStructuralEquatable `were introduced in .NET 4.0 to assist in supporting Tuples.

A tuple is equal to another if and only if all items are equal, i.e., `t1.Item1 ==t2.Item1 and ``t1.Item2 == t2.Item2`, and so on.

To sort, a comparison is made on individual items, i.e., the comparison is made in the first `Item1 `if `t1.Item1> t2.Item1 `then Tuple `t2 `is the smallest, if `t1.Item1 == t2.Item1` then the comparison is made in `item2 `and so on.

To use the interfaces `IComparable`, `IEquatable`, `IStructuralComparable `and `IStructuralEquatable`, we must make the cast to the desired interface explicitly.
```Tuple<int, int> t1 = Tuple.Create(3, 9);
Tuple<int, int> t2 = Tuple.Create(3, 9);
Tuple<int, int> t3 = Tuple.Create(9, 3);
Tuple<int, int> t4 = Tuple.Create(9, 4);

Console.WriteLine("t1 = t2 : {0}", t1.Equals(t2)); //true
Console.WriteLine("t1 = t2 : {0}", t1 == t2); //false
Console.WriteLine("t1 = t3 : {0}", t1.Equals(t3)); // false

Console.WriteLine("t1 < t3 : {0}", ((IComparable)t1).CompareTo(t3) < 0); //true
Console.WriteLine("t3 < t4 : {0}", ((IComparable)t3).CompareTo(t4) < 0); //true```

Conclusion

While the indiscriminated use of Tuples affects the readability of the code, its use at the appropriate time can be very handy for developers, allowing them to return multiple values from a function without the need to create parameters "`ref`" and `/` or "`out`", allowing the creation of composite keys to collections of type `Dictionary `and eliminates the need to create `struct`s or `class`es or just to fill combobox or lists.

History

• 9th May, 2011: Initial post

Share

 Software Developer (Senior) ResourceKraft Ireland
I'm a Brazilian senior system analyst living in Limerick, Ireland. I've been working with software development since 1996.

You may also be interested in...

 First PrevNext
 My vote of 5 Snesh Prajapati10-Nov-13 19:51 Snesh Prajapati 10-Nov-13 19:51
 Friends DONT let Friends use Tuples! rittjc11-May-13 13:35 rittjc 11-May-13 13:35
 Re: Friends DONT let Friends use Tuples! yloginov27-May-13 5:50 yloginov 27-May-13 5:50
 Re: Friends DONT let Friends use Tuples! rittjc27-May-13 19:17 rittjc 27-May-13 19:17
 Re: Friends DONT let Friends use Tuples! yloginov28-May-13 3:47 yloginov 28-May-13 3:47
 Re: Friends DONT let Friends use Tuples! rittjc28-May-13 12:13 rittjc 28-May-13 12:13
 Nice one! Naerling29-Mar-13 21:15 Naerling 29-Mar-13 21:15
 Personally I don't like tuples because, as you say, they make code less readable. I've used them once and when I came back to that app some weeks later I had already forgotten what the values represent. I had to look pretty hard to find out. I had never though about using them for comparison or composite dictionary key. Those seem like good idea's (a distionaries key is 'unnamed' already anyways). Weren't they introduced to .NET for compatibility with F#? In F# you don't use a tuple object (directly), a function can simply return more than one value (for example: return 1, "Hello"). When referencing these functions in C# or VB their return value is translated to Tuple. Nice article anyway. My 5. It's an OO world. ```public class Naerling : Lazy{ public void DoWork(){ throw new NotImplementedException(); } }```
 My vote of 5 Belial0916-Jan-13 21:32 Belial09 16-Jan-13 21:32
 Iterate over two or more collections daflodedeing22-Nov-12 22:31 daflodedeing 22-Nov-12 22:31
 tuples arup200514-Jul-12 7:02 arup2005 14-Jul-12 7:02
 My vote of 5 Akram El Assas11-May-12 10:39 Akram El Assas 11-May-12 10:39
 Re: My vote of 5 fmsalmeida11-May-12 11:39 fmsalmeida 11-May-12 11:39
 My vote of 5 Dave Kerr12-Feb-12 12:11 Dave Kerr 12-Feb-12 12:11
 My vote of 5 DaveyM695-Dec-11 8:56 DaveyM69 5-Dec-11 8:56
 +5 and a question ... BillWoodruff5-Dec-11 7:00 BillWoodruff 5-Dec-11 7:00
 'unreadable' is a little harsh dave.dolan19-Jun-11 18:11 dave.dolan 19-Jun-11 18:11
 Re: 'unreadable' is a little harsh fmsalmeida20-Jun-11 2:38 fmsalmeida 20-Jun-11 2:38
 My vote of 5 Jonathan Cardy19-Jun-11 1:14 Jonathan Cardy 19-Jun-11 1:14
 Re: My vote of 5 fmsalmeida20-Jun-11 2:37 fmsalmeida 20-Jun-11 2:37
 My vote of 5 Monjurul Habib17-Jun-11 10:39 Monjurul Habib 17-Jun-11 10:39
 Re: My vote of 5 fmsalmeida20-Jun-11 2:36 fmsalmeida 20-Jun-11 2:36
 My vote of 5 Andy Missico15-Jun-11 9:17 Andy Missico 15-Jun-11 9:17
 Re: My vote of 5 fmsalmeida20-Jun-11 2:36 fmsalmeida 20-Jun-11 2:36
 nice CIDev13-Jun-11 4:19 CIDev 13-Jun-11 4:19
 Re: nice fmsalmeida13-Jun-11 4:31 fmsalmeida 13-Jun-11 4:31
 Last Visit: 31-Dec-99 18:00     Last Update: 19-Aug-17 19:21 Refresh 123 Next »