2009-07-31 8 views
91

Metody są dostępne w Linq. Co każdy programista powinien wiedzieć o tych dwóch metodach? Na przykład: kiedy używać jednej na drugiej, wszelkie zalety korzystania z jednego nad drugim, itp.Linq: Jaka jest różnica między Select i Where

+5

Nie sądzę, że to pytanie powinno być oznaczone jako CW, może to dać ostateczną odpowiedź. – Brandon

+1

@Bandon nie ma nic złego w oznaczaniu czegoś CW, jeśli jest obiektywne. –

+0

@Rex, zgadzam się. Mówiąc tylko, że różnica między Select i Where ma ostateczną odpowiedź, a druga część pytania prawdopodobnie opierałaby się na powszechnie akceptowanych praktykach. Po prostu wskazałem to na wypadek, gdyby OP nie miał pewności co do oznaczania rzeczy jako CW. Gdyby chciał, żeby to było CW, to w porządku przeze mnie. – Brandon

Odpowiedz

90

Gdzie

znajdzie elementy, które pasują i zwraca tylko tych, które (filtrowanie).

->IEnumerable<A> w, IEnumerable<A> z

Wybierz

powraca coś dla wszystkie przedmiotów w źródle (projekcja/transformacji). To coś może być same w sobie, ale zwykle jest to jakaś projekcja.

->IEnumerable<A> w, IEnumerable<B> z

+5

'Wybierz' zawsze zwróci taką samą liczbę elementów na liście (niezależnie od stanu filtru, jaki możesz mieć). 'Gdzie 'może zwrócić mniej elementów w zależności od stanu filtra. –

+0

I [tutaj] (https://msdn.microsoft.com/en-us/library/bb548891 (v = vs.110) .aspx) jest przykładem MSDN z 'select' i [here] (https: // msdn.microsoft.com/en-us/library/bb534803(v=vs.110).aspx) jest dla 'where' – yazanpro

+0

Przynajmniej dla mnie, mając pewne doświadczenie z innymi językami, pomaga myśleć, że' 'Gdzie == filter'' i '' Wybierz == map'' – bgusach

15

Wybrać mapy przeliczalne na nową strukturę. Jeśli dokonasz wyboru na IEnumerable, otrzymasz tablicę z taką samą liczbą elementów, ale inny typ w zależności od określonego odwzorowania. Gdzie filtruje IEnumerable tak, że daje ci podzbiór oryginalnego IEnumerable.

33

Są odrębne:

Select jest o transformacja.

Where to wszystko o filtrowaniu.

37

Wybierz i Gdzie są dwie zupełnie różne podmioty działające na IEnumerable s.

Pierwszy z nich to, co nazywamy operatorem Projekcję, natomiast ostatni jest operatorem Ograniczenie.

Interesującym sposobem na poznanie zachowania takich operatorów jest spojrzenie na ich "typ funkcjonalny".

  • Wybierz (IEnumerable < T1>, funkc < T1, T2>) → IEnumerable < T2>; jako dane wejściowe przyjmuje zarówno elementy IEnumerable zawierające typ T1, jak i funkcję przekształcającą elementy typu T1 w elementy typu T2. Dane wyjściowe są elementami zawierającymi IEnumerable typu T2.

    Z tego można łatwo zgadnąć, że ten operator będzie produkować swoje wyjście poprzez zastosowanie funkcji wprowadzania na każdym elemencie wejścia IEnumerable i zawijanie wyników wewnątrz nowego IEnumerable.

    Posługując się jakąś notacją matematyczną, przyjmuje jako dane wejściowe (a, b, c, ...) IEnumerable < T1> i F T1 → T2 i wytwarza (F (a), F (b), F (C), ...) IEnumerable < T2>

  • Gdzie: (IEnumerable < T1>, Func < T1, bool>) → IEnumerable < T1>; ten pobiera elementy IEnumerable zawierające typ T1 i predykat na T1 (to znaczy funkcję, która daje wynik boolowski dla wejścia typu T1). Widzisz, że wyjście jest również elementem zawierającym IEnumerable typu T1.

    Tym razem można by przypuszczać, że element wejścia IEnumerable będzie obecny na wyjściu IEnumerable w zależności od wyniku zastosowania predykatu do elementu. Dodając do tego semantykę nazwy operatora, możesz być pewny, że wygeneruje on wynik IEnumerable, pobierając z wejścia tylko te elementy, które są prawdziwe w zastosowaniu predykatu.

Osób funkcjonalnego programowania tle zwykle myśleć w ten sposób. Pozwala na wywnioskowanie (a przynajmniej odgadnięcie ...) tego, co robi operator, tylko patrząc na jego typ!

Jako ćwiczenie, spróbuj spojrzeć na innych operatorów wprowadzonych przez LINQ na IEnumerables i wywnioskować ich zachowanie, zanim przejrzysz dokumentację!

6

Jeśli wiesz, w jaki sposób zaimplementowano Gdzie i wybierz metody rozszerzenia, możesz przewidzieć, co robi ... Próbowałem zaimplementować miejsce i wybrać metody rozszerzeń ... Możesz spojrzeć na to ...

Gdzie realizacja ::

public static IEnumerable<Tsource> Where<Tsource> (this IEnumerable<Tsource> a , Func<Tsource , bool> Method) 
{ 

    foreach (var data in a) 
    { 
     //If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return) 
     if (Method.Invoke (data)) 
     { 
      yield return data; 
     } 
    } 
} 

Wybierz realizacja ::

public static IEnumerable<TResult> Select<TSource , TResult> (this IEnumerable<TSource> a , Func<TSource , TResult> Method) 
{ 
    foreach (var item in a) 
    { 
     //Each iteration call the delegate and return the Data back.(use 'yield' for deferred return) 
     yield return Method.Invoke (item); 
    } 
} 

Moja implementacja działa dobrze dla każdej kolekcji .. Ale różni się od implementowanych przez Microsoft metod rozszerzeń, ponieważ używają drzewek wyrażeń do ich implementacji.