Używam LINQ w moim codziennym programowaniu. W rzeczywistości rzadko, jeśli w ogóle, używam wyraźnej pętli. Odkryłem jednak, że nie używam już składni podobnej do SQL. Po prostu używam funkcji rozszerzenia. Zamiast mówić:
from x in y select datatransform where filter
Używam:
x.Where(c => filter).Select(c => datatransform)
Który styl LINQ preferujesz i z kim inni w twoim zespole czują się komfortowo?
c#
coding-style
linq
Erin
źródło
źródło
Odpowiedzi:
Uważam za niefortunne, że stanowisko Microsoftu według dokumentacji MSDN jest takie, że preferowana jest składnia zapytania, ponieważ nigdy jej nie używam, ale cały czas używam składni metody LINQ. Uwielbiam być w stanie odpalać zapytania jednowierszowe do treści mojego serca. Porównać:
Do:
Szybciej, mniej linii, a moim oczom wygląda na czystsze. Składnia zapytania nie obsługuje również wszystkich standardowych operatorów LINQ. Przykładowe zapytanie, które ostatnio zrobiłem, wyglądało mniej więcej tak:
Według mojej wiedzy, aby zreplikować to zapytanie przy użyciu składni zapytania (w możliwym zakresie), wyglądałoby to tak:
Nie wydaje mi się bardziej czytelny i i tak musisz wiedzieć, jak korzystać ze składni metod. Osobiście jestem naprawdę zachwycony deklaratywnym stylem, który umożliwia LINQ i używam go w każdej sytuacji, w której jest to w ogóle możliwe - być może czasami na moją szkodę. W tym przypadku ze składnią metody mogę zrobić coś takiego:
Wyobrażam sobie, że powyższy kod byłby trudny do zrozumienia dla kogoś wchodzącego do projektu bez dobrej dokumentacji, a jeśli nie mają solidnego doświadczenia w LINQ, mogą go nie zrozumieć. Mimo to składnia metody ujawnia pewne dość potężne możliwości szybkiego wyświetlania (w kategoriach wierszy kodu) zapytania w celu uzyskania zbiorczych informacji o wielu kolekcjach, które w innym przypadku wymagałyby wielu żmudnych pętli foreach. W takim przypadku składnia metody jest ultra-kompaktowa dla tego, co z niej wyciągniesz. Próba zrobienia tego za pomocą składni zapytania może stać się niewygodna dość szybko.
źródło
Uważam, że funkcjonalna składnia jest przyjemniejsza dla oka. Jedynym wyjątkiem jest to, że muszę dołączyć więcej niż dwa zestawy. Join () bardzo szybko wariuje.
źródło
Czy jest już za późno, aby dodać kolejną odpowiedź?
Napisałem mnóstwo kodu LINQ-to-objects i twierdzę, że przynajmniej w tej domenie dobrze jest zrozumieć obie składnie, aby zastosować którykolwiek z nich, który upraszcza kod - który nie zawsze jest składnią kropkową.
Oczywiście zdarzają się sytuacje, w których składnia kropkowa JEST właściwą drogą - inni podali kilka takich przypadków; myślę jednak, że zmieniono rozumienie - jeśli źle zrobisz, otrzymałeś zły rap. Podam więc próbkę, w której, moim zdaniem, zrozumienie jest przydatne.
Oto rozwiązanie zagadki polegającej na zastępowaniu cyfr: (rozwiązanie napisane przy użyciu LINQPad, ale może być samodzielne w aplikacji na konsolę)
... które wyjścia:
Nieźle, logika płynie liniowo i widzimy, że powstaje jedno poprawne rozwiązanie. Ta łamigłówka jest łatwa do rozwiązania ręcznie: rozumowanie, że 3>>
N
0 iO
> 4 * N implikuje 8> =O
> = 4. Oznacza to, że istnieje maksymalnie 10 przypadków do przetestowania ręcznie (2 dlaN
- by -5 dlaO
). Wystarczająco zbłądziłem - ta łamigłówka jest oferowana w celach ilustracyjnych LINQ.Transformacje kompilatora
Kompilator robi wiele, aby przetłumaczyć to na równoważną składnię kropkową. Poza zwykłymi drugimi i kolejnymi
from
klauzulami zamienianymi wSelectMany
wywołania , mamylet
klauzule, które stają sięSelect
wywołaniami z rzutami, które wykorzystują przezroczyste identyfikatory . Jak zamierzam pokazać, konieczność nazwania tych identyfikatorów w składni kropek odbiera czytelność tego podejścia.Mam sposób na ujawnienie, co robi kompilator, tłumacząc ten kod na składnię kropkową. Jeśli usuniesz komentarz z dwóch wyżej wymienionych wierszy i uruchom go ponownie, otrzymasz następujące dane wyjściowe:
Umieszczenie każdego operatora LINQ w nowym wierszu, tłumaczenie „niewymownych” identyfikatorów na te, które możemy „wypowiedzieć”, zmiana typów anonimowych na ich znaną formę i zmiana języka
AndAlso
lingwistycznego drzewa wyrażeń w celu&&
ujawnienia transformacji, które kompilator robi, aby osiągnąć równoważny w składni kropkowej:Co, jeśli uruchomisz, możesz sprawdzić, czy to ponownie generuje:
... ale czy kiedykolwiek napisałbyś taki kod?
Założę się, że odpowiedź brzmi NONBHN (nie tylko nie, ale piekło nie!) - ponieważ jest to po prostu zbyt skomplikowane. Jasne, że możesz wymyślić bardziej znaczące nazwy identyfikatorów niż „temp0” .. „temp3”, ale chodzi o to, że nie dodają niczego do kodu - nie poprawiają kodu, nie poprawiają sprawi, że kod będzie lepiej czytany, tylko brzydko go poprawiają, a jeśli robisz to ręcznie, bez wątpienia zepsułbyś go raz lub trzy, zanim zrobisz to poprawnie. Ponadto granie w „grę z imionami” jest wystarczająco trudne do uzyskania znaczących identyfikatorów, dlatego z zadowoleniem przyjmuję odejście od gry z imionami, które kompilator zapewnia mi w zrozumieniu zapytań.
Próbka ta zagadka może nie być w świecie rzeczywistym na tyle, aby podjąć poważnie; istnieją jednak inne scenariusze, w których świecą pojęcia zapytań:
Join
iGroupJoin
: zakres zmiennych zasięgu wjoin
klauzulach rozumienia zapytań zamienia błędy, które w przeciwnym razie mogłyby się kompilować w składni kropkowej, w błędy czasu kompilacji w składni rozumienia.from
klauzul orazjoin
&join..into
ilet
klauzul.Znam więcej niż jeden warsztat inżynieryjny w moim rodzinnym mieście, który zabronił składni rozumienia. Myślę, że szkoda, ponieważ składnia rozumienia jest tylko narzędziem i jest w tym przydatna. Myślę, że to tak, jakby powiedzieć: „Są rzeczy, które można zrobić za pomocą śrubokręta, których nie można zrobić za pomocą dłuta. Ponieważ można użyć śrubokręta jako dłuta, dłuta są odtąd zakazane na mocy dekretu króla”.
źródło
Radzę używać składni rozumienia zapytania, gdy całe wyrażenie można wykonać w składni rozumienia. To znaczy wolałbym:
do
Ale wolałbym
do
Chciałbym wymyślić jakąś składnię, która sprawiła, że fajniej było mieszać te dwa. Coś jak:
Ale niestety nie zrobiliśmy tego.
Ale w zasadzie jest to kwestia preferencji. Zrób ten, który wygląda lepiej dla ciebie i twoich współpracowników.
źródło
var londonCustomers = from c in ...; int count = londonCustomers.Count();
SQL-like to dobry sposób na rozpoczęcie. Ale ponieważ jest ograniczony (obsługuje tylko te konstrukcje, które obsługuje Twój obecny język), w końcu programiści wybierają styl rozszerzeń.
Chciałbym zauważyć, że istnieją pewne przypadki, które mogą być łatwo zaimplementowane w stylu SQL.
Możesz także połączyć oba sposoby w jednym zapytaniu.
źródło
Zwykle używam składni bez zapytania, chyba że muszę zdefiniować zmienną w połowie drogi, chociaż zapytanie jest podobne
ale piszę składnię bez zapytań jak
źródło
Zawsze korzystam z funkcji rozszerzenia z powodu zamawiania. Weźmy prosty przykład - w SQL, najpierw napisałeś select - nawet jeśli faktycznie wykonano go jako pierwszy. Kiedy piszesz przy użyciu metod rozszerzenia, mam większą kontrolę. Dostaję Intellisense o tym, co jest w ofercie, piszę rzeczy w kolejności, w jakiej się pojawiają.
źródło
Lubię też funkcję rozszerzenia.
Może dlatego, że w moim umyśle jest to mniejszy skok składni.
Jest również bardziej czytelny dla oka, szczególnie jeśli używasz frameworków innych firm, które mają interfejs linq api.
źródło
Oto heurystyka, którą śledzę:
Myślę, że lambdas ze złączami wyglądają na bałagan i są trudne do odczytania.
źródło