Najprostsza postać Tupla to ta znana przed C# 7.0:
var person = new Tuple<string, string, int>("Jacek", "Kowalski", 10); Console.WriteLine($"My name is {person.Item1} {person.Item2}. I'm {person.Item3} years old.");
Składnia ta nie pozwala na nazwanie poszczególnych składowych. Do poszczególnych składowych odwołujemy się poprzez składowe ItemX gdzie X to numer pola.
Zastosowanie pól numerowanych nie jest wygodnym rozwiązaniem i z pewnością nie motywowało do częstego używania Tupli. Wszystko zmieniło się wraz z C# 7.0 gdzie wprowadzono nową składnię:
(string FirstName, string LastName, int Age) person = ("Jacek", "Kowalski", 10); Console.WriteLine($"My name is {person.FirstName} {person.LastName}. I'm {person.Age} years old.");
Zapis możemy skrócić korzystając z słówka var:
var person = (FirstName: "Jacek", LastName: "Kowalski", Age: 10); Console.WriteLine($"My name is {person.FirstName} {person.LastName}. I'm {person.Age} years old.");
Zapis możemy jeszcze bardziej skrócić, jednak wtedy wracamy do dawnej konwencji nazywania składowych Tupla Item:
var person = ("Jacek", "Kowalski", 10); Console.WriteLine($"My name is {person.Item1} {person.Item2}. I'm {person.Item3} years old.");
Warto wspomnieć jeszcze o dekonstrukcji Tupla na jego poszczególne składowe. Oczywiście do poszczególnych składowych można odnieść się po nazwie pola / ItemX. Warto jednak wiedzieć, że istnieje alternatywa:
var (firstName, lastName, age) = person; Console.WriteLine($"My name is {firstName} {lastName}. I'm {age} years old.");
Teraz zastanówmy się nad tym kiedy używać Tupli a kiedy nie. Zacznijmy od kilku ich właściwości, które mogą pomóc zdecydować czy je używać czy nie:
- Zdefiniowane nazwy składowych Tupla nie są stałe - podczas działania programu znikają.
- Nowy Tupl to instancja struktury ValueTuple<T> - typ wartościowy, więc przekazywany jest przez wartość. Problem częstego kopiowania można zaadresować przez zastosowanie ref local / ref return
- Tuple pozwalają na porównywanie za pomocą == czy !=
Kiedy więc warto skorzystać z Tupli? Z pewności w metodach prywatnych biblioteki czy klasy. Pozwala to uniknąć tworzenia kolejnych definicji obiektów. W przypadku publicznych API nie jest zalecane używanie Tupli.