Wprowadzenie do krotek w C# w 10 minut lub mniej
[[academy-video-youtube({"vid": "QC6hpl2iU0c", "start_time": "0", "title": "Intro to Tuples in C# In 10 Minutes or Less", "creator": "Tim Corey", "length": "9m 49s"})]]
Metody w C# są zaprojektowane na podstawie pojedynczej wartości zwracanej, co działa do momentu, gdy jedno zwracanie faktycznie nie wystarczy. Walidacja adresu to klasyczny przykład: musisz wiedzieć, czy dane wejściowe są prawidłowe, a jeśli są, chcesz otrzymać z powrotem prawidłowy, sformatowany formularz. Otaczanie tej pary w nowej klasie wydaje się ciężkie dla jednej metody, a parametry out mieszają wejście i wyjście w sposób, który źle się starzeje. Krotki zostały dodane do języka, aby ta sytuacja miała bardziej przejrzystą odpowiedź.
W swoim filmie "Intro to Tuples in C# In 10 Minutes or Less", Tim Corey przechodzi przez krotki, budując małą metodę walidacji adresu, która potrzebuje zwrócić zarówno sformatowany ciąg, jak i znacznik ważności. Po drodze omawia składnię zwracania krotki, dlaczego nazewnictwo członków jest istotne, jak rozdzielić wynik na osobne zmienne w miejscu wywołania i jak pominąć części, które Cię nie interesują, za pomocą znaku odrzutu. Czytelnicy, którzy wciąż sięgają po klasy wynikowe jednorazowego użytku lub parametry out, znajdą tutaj lżejszy wzorzec.
Problem: Zwracanie więcej niż jednej wartości
[0:18 - 2:50] Tim rozpoczyna od metody ValidateAddress, która akceptuje ciąg znaków adresu ulicy. Zachowanie, które chce osiągnąć, jest proste: jeśli dane wejściowe odpowiadają "123 Sesame St", zwróć poprawnie sformatowane "123 Sesame Street"; w przeciwnym razie sygnalizuj, że adres jest nieprawidłowy. Dwa elementy informacji muszą wrócić z jednego wywołania, sformatowany ciąg i znacznik sukcesu.
Opcje przed krotkami są niezręczne. Utworzenie klasy ValidateAddressResult działa, ale pozostawia typ jednorazowego użytku w projekcie, którego żaden inny kod nigdy nie zainstancjuje. Użycie parametru out do przesłania sformatowanego adresu z powrotem przez listę parametrów działa też, ale miesza wejście i wyjście w sygnaturze metody i sprawia, że miejsce wywołania jest trudniejsze do odczytania. Krotki zostały wprowadzone, aby radzić sobie z tym przypadkiem bez ponoszenia żadnego z kosztów.
Zwracanie nienazwanej krotki
[2:50 - 4:01] Minimalna składnia dla typu zwrotnego krotki zawiera dwa typy w nawiasach:
public (string, bool) ValidateAddress(string address)
{
if (address == "123 Sesame St")
{
return ("123 Sesame Street", true);
}
return (address, false);
}public (string, bool) ValidateAddress(string address)
{
if (address == "123 Sesame St")
{
return ("123 Sesame Street", true);
}
return (address, false);
}Metoda teraz zwraca parę (string, bool). Minus pojawia się natychmiast, gdy coś próbuje go użyć. Bez przypisanych nazw do członków, IntelliSense ukazuje je jako Item1 i Item2, co nie mówi kolejnemu czytelnikowi, co reprezentuje każda wartość. Tim wskazuje, że to jest powodem, dla którego nigdy nie dostarcza nieznakowanych krotek, mimo że składnia jest najkrótsza. Koszt czytania result.Item2 sześć miesięcy później jest wyższy niż koszt wpisania nazwy raz.
Nazywanie członków krotki
[4:01 - 6:30] Przypisanie nazw każdemu członkowi krotki to jednolinijkowa zmiana w deklaracji typu zwrotnego:
public (string Address, bool IsValid) ValidateAddress(string address)
{
if (address == "123 Sesame St")
{
return ("123 Sesame Street", true);
}
return (address, false);
}public (string Address, bool IsValid) ValidateAddress(string address)
{
if (address == "123 Sesame St")
{
return ("123 Sesame Street", true);
}
return (address, false);
}Teraz miejsce wywołania wygląda naturalnie:
var result = ValidateAddress("123 Sesame St");
if (result.IsValid)
{
Console.WriteLine($"Your validated address is {result.Address}");
}
else
{
Console.WriteLine("That is an invalid address");
}var result = ValidateAddress("123 Sesame St");
if (result.IsValid)
{
Console.WriteLine($"Your validated address is {result.Address}");
}
else
{
Console.WriteLine("That is an invalid address");
}Uruchomienie kodu z "123 Sesame St" drukuje kanoniczną formę. Usunięcie początkowej liczby 1, aby uzyskać "23 Sesame St" sprawia, że IsValid zwraca false i wyświetla komunikat o nieprawidłowym adresie. Kontrakt metody teraz dokumentuje się sam na miejscu wywołania bez nazwanej krotki, wymagając pliku klasy pomocniczej.
Krotka może przenosić więcej niż dwóch członków. Trzy, cztery, czy pięć działają tak samo. Tim zauważa, że gdy krotka rośnie poza trzy lub cztery członki, rekord lub klasa zazwyczaj staje się bardziej przejrzystą opcją, ale dla dwóch lub trzech powiązanych wartości z jednej metody, krotka pozostaje lżejszym wyborem.
Dekonstrukcja krotki do osobnych zmiennych
[6:30 - 7:39] Czasami wywołujący woli trzymać każdą część wyniku w swojej własnej zmiennej zamiast sięgać do jednej result. C# wspiera to bezpośrednio za pomocą składni dekonstrukcji:
(string message, bool valid) = ValidateAddress("123 Sesame St");
if (valid)
{
Console.WriteLine($"Your validated address is {message}");
}(string message, bool valid) = ValidateAddress("123 Sesame St");
if (valid)
{
Console.WriteLine($"Your validated address is {message}");
}Nazwy zmiennych po lewej stronie nie muszą pasować do nazw członków krotki w metodzie. Tutaj message zastępuje Address a valid zastępuje IsValid. Tim zauważa, że jest to dekonstruktor, nie destruktor; dwa słowa brzmią podobnie, ale odnoszą się do zupełnie różnych pojęć. Dekonstruktor rozdziela krotkę na lokalne zmienne, które faktycznie potrzebują oprogramowanie.
Pomijanie wartości znakiem odrzutu
[7:41 - 8:54] Kiedy wywołujący interesuje się tylko częścią zwróconych wartości, znak odrzutu (_) pomija te, które są niepotrzebne:
(string message, _) = ValidateAddress("123 Sesame St");
Console.WriteLine(message);(string message, _) = ValidateAddress("123 Sesame St");
Console.WriteLine(message);Podkreślenie mówi kompilatorowi "Celowo ignoruję tę wartość". Jest to bardziej wyraziste niż przypisanie niechcianego członka do nazwy zmiennej niepodręcznej, takiej jak unused, ponieważ odrzut komunikuje intencję. Każdy, kto czyta linię, wie, że ignorowanie IsValid jest celowym wyborem dla tego miejsca wywołania, a nie przeoczeniem.
Zakończenie: Kiedy krotki zasługują na swoje miejsce
[8:54 - 9:28] Główny powód użycia krotek to zwracanie kilku wartości z metody bez tworzenia klasy, która istnieje tylko, by zostać zwrócona raz. Nazewnictwo członków w sygnaturze metody, ich dekonstrukcja w miejscu wywołania i odrzucenie tych, których wywołujący nie potrzebuje, to trzy wzorce, które sprawiają, że krotki są wygodne do życia z nimi. Poza tym krotki są przydatne w projekcjach LINQ i kalkulacjach pośrednich, gdzie szybka wartość parowa jest bardziej czytelna niż anonimowy typ.
Wnioski
[9:28 - 9:49] Krotki dają C# zwięzły sposób na zwrócenie więcej niż jednej wartości z metody. Nazwana forma jest wersją wartą używania na co dzień, ponieważ result.Address czyta, podczas gdy result.Item1 nie. Dekonstrukcja promuje części z powrotem do lokalnych zmiennych, gdy wywołujący woli ten kształt, a znak odrzutu pozwala, aby jedno wywołanie zabrało tylko to, czego potrzebuje.
Porada: Kiedy zaczynasz dekonstruować ten sam kształt krotki w trzech lub więcej miejscach, to sygnał, by przejść na rekord zamiast. Krotki błyszczą, gdy kształt jest lokalny dla jednej metody; w momencie, gdy kształt staje się częścią Twojej domeny, nazwany typ sam się spłaci.
Oglądaj pełne wideo na jego kanale YouTube Channel i zyskaj więcej wglądu w pisanie nowoczesnego, wyrazistego C# w serii 10-Minute Training.

