Klasa (immutable) Tuple istniała aż od .NET Framework 4.0. W C# 7.0 mamy jednak wsparcie dla tuple od strony języka. Jednym z problemów klasy Tuple było, że każda właściwość nazywała się kolejno Item1, Item2 itp.
Przykład:
class Program { private static void Main(string[] args) { var tuple = GetFirstAndLastName(); Console.WriteLine(tuple.Item1); Console.WriteLine(tuple.Item2); } private static Tuple<string,string> GetFirstAndLastName() { var tuple = new Tuple<string, string>("Piotr", "Zielinski"); return tuple; } }
W wersji 7.0, powyższy kod możemy przepisać do:
class Program { private static void Main(string[] args) { var tuple = GetFirstAndLastName(); Console.WriteLine(tuple.firstName); Console.WriteLine(tuple.lastName); } private static (string firstName, string lastName) GetFirstAndLastName() { var fullName = (firstName: "Piotr", lastName: "Zielinski"); return fullName; } }
Składnia dużo czytelniejsza ponieważ nie operujemy już na Item1 i Item2. Zobaczmy co się kryje za tym nowym “Tuple” po dekompilacji:
internal class Program { // Method .ctor with token 06000003 public Program() { base.\u002Ector(); } // Method Main with token 06000001 private static void Main(/*Parameter with token 08000001*/string[] args) { ValueTuple<string, string> firstAndLastName = Program.GetFirstAndLastName(); Console.WriteLine(firstAndLastName.Item1); Console.WriteLine(firstAndLastName.Item2); } // Method GetFirstAndLastName with token 06000002 private static ValueTuple<string, string> GetFirstAndLastName() { return new ValueTuple<string, string>("Piotr", "Zielinski"); } }
Całość opiera się na zwykłej strukturze ValueTuple<string, string>. Wygląda to bardzo analogicznie do starego Tuple<T1,T2>. Zaglądając do źródeł ValueTuple, przekonamy się, że klasa jest immutable i przeładowuje metody typu Equals oraz GetHashCode. Oznacza to, że typ doskonale nadaję się jako klucz do słowników.
Powyższy kod można przetestować używając Visual Studio ’15’ preview 3, który jest dostępny tutaj.
Hej, używasz w codziennej pracy tego typu? To nie jest przypadkiem jakiś antywzorzec?
Choć faktycznie w C# 7 z możliwością nadawania nazw już to jest bardziej czytelne.
Tworze zawsze swoje typy. Jedynie zastsosowanie starego Tuple to moze prywatne metody ale i to jest dosc brzydkie.
Rzeczywiście nie jest to eleganckie rozwiązanie. Kilka razy zastosowałem Tuple, kiedy zależało mi na dowiezieniu pilnego tematu i już nie miałem siły/czasu tworzyć kolejnych modelów (jeden prosty kontener danych) i przekopywać się przez kolejne warstwy aplikacji z Automapperami ;]
Ponieważ pod spodem kompilator używa ValueTuple ciekawe w jaki sposób będzie pilnował nazw elementów (firstName, lastName)? Być może tak jak z typami anonimowymi nie będzie ich można współdzielić pomiędzy assembly…
Ciekawe jestem w jaki sposób kompilator będzie sprawdzał nazwy propert – ValueTuple niesie ze sobą informację tylko o typie składowych… Zapewne skończy się jak z anonymous types których można używać tylko w obrębie jednego assembly, a było by naprawdę fajnie móc deklarować publiczne metody które zwracają nazwane tuple.
A jakie znaczenie mają jakieś nazwy? Przecież tuple to krotka, ta zaś z definicji jest uporządkowaną listą wartości określonych typów.