Les Tuples avec C# 7

C# 7 apporte un ensemble de petites nouveautés dont une que je vais vous expliquer dans cet article : les Tuples. En réalité, nous allons parler davantage d'une amélioration que d'une nouveauté puisque cette notion existait déjà avec l'introduction du framework .NET 4.

Utilisation

Concrètement, les avantages d'un type tuple sont multiples. Elle vous permet de manipuler et de retourner plusieurs objets de différents types sans avoir à créer une classe spécifique ou encore d'un tableau d'objets génériques. Nous allons dans un premier temps voir comment fonctionne l'ancienne méthode avant de vous présenter la nouvelle.

Ancienne méthode avec "System.Tuple"

Tout d'abord, voici la création d'un objet de type tuple :

// Création en utilisant la méthode statique 
var nameAndAge = Tuple.Create("jean-luc", 30);

// ou encore en utilisant le constructeur :
var nameAndAge = new Tuple<string, int>("jean-luc", 30);

Ensuite, l'accès aux valeurs du Tuple se fait grâce aux propriétés "Item1", "Item2", "Item3", etc.

var name = nameAndAge.Item1;
var age = nameAndAge.Item2;

Nouvelle méthode avec "System.ValueTuple"

Attention car la nouvelle méthode nécesite l'ajout de la référence "System.ValueTuple" disponible avec NuGet. Une fois fait, vous serez alors en mesure de déclarer un Tuple littéralement comme ceci :

var nameAndAge = (Name: "jean-luc", Age: 30);

et l'utiliser directement avec le nom de la propriété :

var name = nameAndAge.Name;

Bien sûr, la véritable utilité de ces tuples est de pouvoir les utiliser au sein d'une méthode comme ceci :

public static (string name, int age) GetPerson()
{
    return ("jean-luc", 30);
}

var person = GetPerson();
Console.WriteLine($"Nom : {person.name}, Prenom : {person.age}");

Au niveau de la décompilation

Une façon de savoir comment fonctionne ce nouveau Tuple est de décompiler ce code et d'observer ce qu'il produit réellement :

private static void Main(string[] args)
{
    ValueTuple<string, int> person = Program.GetPerson();
    Console.WriteLine(string.Format("Nom : {0}, Prenom : {1}", (object) person.Item1, (object) (int) person.Item2));
}

[return: TupleElementNames(new string[] {"name", "age"})]
public static ValueTuple<string, int> GetPerson()
{
    return new ValueTuple<string, int>("jean-luc", 30);
}

Comme vous pouvez le constater, il est bien fait usage ici de la structure ValueTuple ! L'avantage est donc d'être un type valeur (meilleure gestion de la mémoire) et non plus d'être un type référence (intervention du GC) comme ce fut le cas avec l'ancienne méthode.