2011-03-01 17 views
8

wolę używać metody rozszerzenie dla podstawowych operacji LINQ: Where(), Select, ale dla złożonych Select(), SelectMany(), a zwłaszcza OrderBy().ThenBy() sprawozdania znajdę składnia zapytań o wiele bardziej czytelny i naturalny.LINQ rozszerzenie mix i składnia kwerendy

Dziś znalazłem się z następującym zapytaniem:

from c in _myObject.ObjectsParent.ParentsEnumerable 
        .Where(c => 
         c == anotherObject || c.Parent == anotherObject) 
from q in c.MyObjectsEnumerable 
orderby c.SortKey, q.Description 
select new { Item = q, Text = c.Description + " -> " + q.Description }; 

Czy to jest niebezpieczne (dla czytelności, konserwacji, lub jakiegokolwiek innego powodu) mieszania składni kwerendy i przedłużacz?

To może być bardzo subiektywne, jeśli tak, przepraszam, jeśli nie spełnia wymagań dobrego subiektywnego pytania. Daj mi znać, jeśli mogę to poprawić!

Odpowiedz

6

Czy mieszanie składni zapytania i rozszerzenia jest niebezpieczne (dla czytelności, łatwości konserwacji lub z jakiegokolwiek innego powodu)?

Największym niebezpieczeństwem, jakie widzę, jest potencjalne dodanie "niespodzianki" w kodzie, zwłaszcza gdy inni deweloperzy przeglądają.

Z punktu widzenia kompilacji, składnia zapytania jest tłumaczona bezpośrednio na wywołania metody rozszerzającej, więc niekoniecznie występuje tu problem techniczny. Może to jednak oznaczać dodatkowe wywołania metod, których na pierwszy rzut oka nikt nie spodziewałby się wielu programistów. Ten może prowadzić do potencjalnego problemu z utrzymaniem.

To powiedziawszy, jeśli zrobiłem to oszczędnie i bez uzasadnionego powodu, nie uważam, że istnieje prawdziwy problem z wymieszaniem składni. Jest to dość powszechne - na przykład, jeśli chcesz pisać w składni zapytania, ale musisz je w pełni ocenić, często jest on zawijany w nawiasy z dodanym .ToList() - lub jeśli chcesz używać PLINQ ze składnią zapytania, często jest to from x in collection.AsParallel() , która technicznie również miesza składnię ...

+0

Dzięki, to najbardziej bezpośrednio odpowiedziało na większość moich myśli i obaw. – Crisfole

3

Można zrobić coś takiego, aby było łatwiej.

var firstQuery = _myObject.ObjectsParent.ParentsEnumerable 
       .Where(c => c == anotherObject || c.Parent == anotherObject); 

var secondQuery = from q in firstQuery.MyObjectsEnumerable 
        orderby firstQuery.SortKey, q.Description 
        select new { Item = q, 
           Text = firstQuery.Description + " -> " + q.Description }; 

Teraz zapytania nie są mieszane

+1

Pierwszy wiersz jest nieprawidłowy ... należy upuścić „od c w” ... –

+0

myślę @ Reed-Copsey mean't (* nie powinno), ponieważ firstQuery nie ma opisu obiektu byłby tylko jej element. Kod ten nie działa. – jbtule

1

używam metody Extension, mój kolega używa składni zapytania. Nie ma różnicy.

Powiedziałbym jednak, że należy podzielić duże zapytanie na mniejsze w celu debugowania i czytelności, ponieważ zazwyczaj nie ma kosztów czasu.

1

Po wykonaniu tego samodzielnie (choć nie dla .Where, ale dla .Cast) powiedziałbym, że to bardzo zależy od metod wywoływania, do których dzwonisz.

np. Czułem się doskonale uprawniony do używania .Cast, ponieważ nie był dostępny w składniku cukru (AFAIK), ale prawdopodobnie uniknął .W przypadku, ponieważ ma to reprezentację w składni zapytania.

Powiedziawszy to, prawdopodobnie bym użył. Wybierz mutację danych w zapytaniu też ... Ale jestem trochę sadystą.

3

Jest to swego rodzaju wezwanie do oceny, ale wiele pytań typu "najlepsza praktyka" zwykle bywa, przynajmniej na początku. Moja opinia jest taka, że ​​powinieneś użyć jednego lub drugiego w ramach jednego zdania. Nie za żadne "niebezpieczeństwo" związane z miksowaniem, ale dla jasności.

W tym szczególnym przypadku, gdy klauzula jest bardzo prosta, a ja byłaby go w składni zapytania.

Istnieją jednak przypadki, które nie mogą być elegancko wyrażone w składni zapytania. W przypadkach, gdy nie można uniknąć mieszania składni, kwerendy (ponownie IMO) byłyby bardziej czytelne, gdyby podzielić łańcuch metod na własną zmienną, a następnie po prostu odwołać się do tej zmiennej w instrukcji składni zapytań. Stosując je jako model:

//The method chain can be pulled out as its own variable... 
var filteredParents = _myObject.ObjectsParent.ParentsEnumerable 
        .Where(c => c == anotherObject || c.Parent == anotherObject); 

//...which you can then substitute in a now purely query-syntax statement 
from c in filteredParents 
from q in c.MyObjectsEnumerable 
orderby c.SortKey, q.Description 
select new { Item = q, Text = c.Description + " -> " + q.Description }; 
2

nie sądzę, że to niebezpieczne, aby mieszać, to że to zależy od tego, co jest bardziej czytelny, składni zapytań jest bardzo czytelny, ale nie jako flexable, więc mieszanie niektórych łańcuchowym wydaje się mała cena do zapłaty. Domyślam się, że odpowiedź brzmi, czy uważasz, że następujące w pełni powiązane są bardziej czytelne, niż to, co napisałeś, ja osobiście uważam, że twoje jest łatwiejsze do odczytania.

_myObject.ObjectsParent 
      .ParentsEnumerable 
      .Where(c => c == anotherObject || c.Parent == anotherObject) 
      .SelectMany(c => c.MyObjectsEnumerable, (c, q) => new {c, q}) 
      .OrderBy(t => t.c.SortKey) 
      .ThenBy(t => t.q.Description) 
      .Select(t => new {Item = t.q, Text = t.c.Description + " -> " + t.q.Description}); 
Powiązane problemy