Patrzę na nową funkcję C # krotek. Jestem ciekawy, jaki problem miał rozwiązać krotka?
Do czego używasz krotek w swoich aplikacjach?
Aktualizacja
Dzięki za dotychczasowe odpowiedzi, zobaczę, czy mam pewne sprawy w głowie. Jako współrzędne wskazano dobry przykład krotki. Czy to wygląda dobrze?
var coords = Tuple.Create(geoLat,geoLong);
Następnie użyj krotki w ten sposób:
var myLatlng = new google.maps.LatLng("+ coords.Item1 + ", "+ coords.Item2 + ");
Czy to jest poprawne?
Odpowiedzi:
Podczas pisania programów niezwykle często występuje chęć logicznego zgrupowania zestawu wartości, które nie mają wystarczającej wspólności, aby uzasadnić utworzenie klasy.
Wiele języków programowania pozwala na logiczne grupowanie razem zestawu niepowiązanych ze sobą wartości bez tworzenia typu tylko w jeden sposób:
void M(int foo, string bar, double blah)
Logicznie rzecz biorąc, jest to dokładnie to samo, co metoda M, która przyjmuje jeden argument, który jest 3 krotką typu int, string, double. Ale mam nadzieję, że tak naprawdę nie zrobiłbyś:
class MArguments { public int Foo { get; private set; } ... etc
chyba że MArguments miał inne znaczenie w logice biznesowej.
Koncepcja „grupowania razem zbioru niepowiązanych w inny sposób danych w pewną strukturę, która jest lżejsza niż klasa” jest przydatna w wielu, wielu miejscach, nie tylko w przypadku formalnych list parametrów metod. Jest to przydatne, gdy metoda ma dwie rzeczy do zwrócenia lub gdy chcesz wyodrębnić słownik z dwóch danych zamiast jednej, i tak dalej.
Języki, takie jak F #, które natywnie obsługują typy krotek, zapewniają użytkownikom dużą elastyczność; są niezwykle użytecznym zestawem typów danych. Zespół BCL zdecydował się współpracować z zespołem F # w celu ujednolicenia jednego typu krotki dla frameworka, tak aby każdy język mógł z nich skorzystać.
Jednak w tym momencie nie ma obsługi języka dla krotek w C #. Krotki to po prostu inny typ danych, jak każda inna klasa frameworka; nie ma w nich nic specjalnego. Rozważamy dodanie lepszej obsługi krotek w hipotetycznych przyszłych wersjach języka C #. Jeśli ktoś ma jakieś przemyślenia na temat tego, jakie funkcje związane z krotkami chciałbyś zobaczyć, z przyjemnością przekażę je zespołowi projektowemu. Realistyczne scenariusze są bardziej przekonujące niż rozważania teoretyczne.
źródło
Item1
,Item2
itp ... Jeśli krotki kiedykolwiek osiągną wsparcie językowe w C #, byłoby cudownie pozwolić swoim członkom na nadawanie nazw (lub przynajmniej aliasów) w sposób, który pozwala na kod używający aby były bardziej zrozumiałe. W takiej hipotetycznej przyszłości chciałbym również zobaczyć krotki o odpowiednim „kształcie” jako prawne parametry metod, które przyjmują indywidualne parametry (i odwrotnie). WięcTuple<int,string,bool>
można przekazaćM(int,string,bool)
. To znacznie ułatwiłoby zapamiętywanie metod.public
dostępu, anonimowestruct
typy z nienazwanymi członkami . Wolałbym, żeby programista napisał astruct
z nazwanymi członkami i zwrócił to, niż mieć do czynienia z elementemtuple
, który nie mówi mi nic o semantyce swoich członków.Krotki zapewniają niezmienną implementację kolekcji
Oprócz typowych zastosowań krotek:
Niezmienne obiekty są z natury bezpieczne wątkowo:
Z „Immutable Object” na Wikipedii
źródło
Stanowi alternatywę
ref
lubout
jeśli masz metodę, która musi zwrócić wiele nowych obiektów w ramach swojej odpowiedzi.Pozwala również na użycie typu wbudowanego jako typu zwracanego, jeśli wszystko, co musisz zrobić, to połączyć dwa lub trzy istniejące typy i nie chcesz dodawać klasy / struktury tylko dla tej kombinacji. (Czy kiedykolwiek chciałeś, aby funkcja mogła zwrócić typ anonimowy? To jest częściowa odpowiedź na tę sytuację.)
źródło
Często pomocne jest posiadanie typu „para” używanego tylko w szybkich sytuacjach (np. Zwracanie dwóch wartości z metody). Krotki są centralną częścią języków funkcjonalnych, takich jak F #, a C # odebrał je po drodze.
źródło
bardzo przydatne do zwracania dwóch wartości z funkcji
źródło
Osobiście uważam, że krotki są iteracyjną częścią rozwoju, gdy jesteś w cyklu badawczym lub po prostu „grasz”. Ponieważ krotka jest ogólna, myślę o niej podczas pracy z parametrami ogólnymi - szczególnie gdy chcę opracować ogólny fragment kodu i zaczynam od końca kodu, zamiast zadawać sobie pytanie „jak chciałbym to wywołanie patrzeć?".
Dość często zdaję sobie sprawę, że kolekcja, którą tworzy krotka, staje się częścią listy, a wpatrywanie się w List> tak naprawdę nie wyraża intencji listy ani tego, jak ona działa. Często z tym „żyję”, ale mam ochotę manipulować listą i zmieniać wartość - w tym momencie niekoniecznie chcę tworzyć nową krotkę, dlatego muszę utworzyć własną klasę lub strukturę aby go zatrzymać, więc mogę dodać kod manipulacji.
Oczywiście zawsze istnieją metody rozszerzające - ale dość często nie chcesz rozszerzać tego dodatkowego kodu na implementacje ogólne.
Czasami chciałem wyrazić dane jako krotka i nie miałem dostępnych krotek. (VS2008) w takim przypadku właśnie utworzyłem własną klasę Tuple - i nie ustawiam jej jako bezpiecznej dla wątków (niezmiennej).
Myślę więc, że jestem zdania, że krotki są leniwym programowaniem kosztem utraty nazwy typu, która opisuje jego przeznaczenie. Innym kosztem jest to, że musisz zadeklarować podpis krotki, gdziekolwiek jest ona używana jako parametr. Po kilku metodach, które zaczynają wyglądać na rozdęte, możesz poczuć, tak jak ja, że warto utworzyć klasę, ponieważ czyści ona sygnatury metod.
Zwykle zaczynam od publicznego członka klasy, w której już pracujesz. Ale w momencie, gdy wykracza poza zwykły zbiór wartości, pobiera swój własny plik i przenoszę go z klasy zawierającej.
Z perspektywy czasu wydaje mi się, że używam krotek, gdy nie chcę wychodzić i pisać zajęć, a po prostu chcę pomyśleć o tym, co piszę teraz. Co oznacza, że podpis krotki może się bardzo zmienić w tekście przez pół godziny, podczas gdy ja zastanawiam się, jakich danych będę potrzebować dla tej metody i jak zwraca wszystkie wartości, które zwróci.
Jeśli dostanę szansę na refaktoryzację kodu, często będę kwestionować miejsce w nim krotki.
źródło
Stare pytanie od 2010 roku, a teraz w 2017 Dotnet zmienia się i staje się bardziej inteligentny.
C # 7 wprowadza obsługę języka dla krotek, co umożliwia nazwy semantyczne pól krotki przy użyciu nowych, bardziej wydajnych typów krotek.
W porównaniu z 2017 i .Net 4.7 (lub instalując pakiet NuGet System.ValueTuple) możesz tworzyć / używać krotki w bardzo wydajny i prosty sposób:
var person = (Id:"123", Name:"john"); //create tuble with two items Console.WriteLine($"{person.Id} name:{person.Name}") //access its fields
Zwracanie więcej niż jednej wartości z metody:
public (double sum, double average) ComputeSumAndAverage(List<double> list) { var sum= list.Sum(); var average = sum/list.Count; return (sum, average); } How to use: var list=new List<double>{1,2,3}; var result = ComputeSumAndAverage(list); Console.WriteLine($"Sum={result.sum} Average={result.average}");
Aby uzyskać więcej informacji, przeczytaj: https://docs.microsoft.com/en-us/dotnet/csharp/tuples
źródło
Krotka jest często używana do zwracania wielu wartości z funkcji, gdy nie chcesz tworzyć określonego typu. Jeśli znasz Pythona, Python ma to od dawna.
źródło
Zwracanie więcej niż jednej wartości z funkcji. Funkcja getCoordinates () nie jest zbyt użyteczna, jeśli zwraca tylko x, y lub z, ale utworzenie pełnej klasy i obiektu do przechowywania trzech liczb całkowitych również wydaje się dość ciężkie.
źródło
Typowym zastosowaniem może być unikanie tworzenia klas / struktur, które zawierają tylko 2 pola, zamiast tego można utworzyć Tuple (lub na razie KeyValuePair). Użyteczna jako wartość zwracana, unikaj przekazywania N parametrów ...
źródło
Odnajduję KeyValuePair odświeżania w C #, aby wykonać iterację nad par klucz-wartość w słowniku.
źródło
KeyValuePair
można postrzegać jako obejście specjalnego przeznaczenia. W Pythonie iteracja po krotkachdict
zwraca (klucz, wartość).Jest to bardzo pomocne podczas zwracania wartości z funkcji. Możemy odzyskać wiele wartości, co w niektórych scenariuszach jest dość oszczędne.
źródło
Natknąłem się na ten test porównawczy wydajności między krotkami i parami klucz-wartość i prawdopodobnie uznasz to za interesujące. Podsumowując, mówi, że Tuple ma przewagę, ponieważ jest klasą, dlatego jest przechowywana w stercie, a nie w stosie, a kiedy jest przekazywana jako argument, jedyną rzeczą, która się dzieje, jest jej wskaźnik. Ale KeyValuePair to struktury, więc alokacja jest szybsza, ale wolniejsza, gdy jest używana.
http://www.dotnetperls.com/tuple-keyvaluepair
źródło