Select
I Where
metody są dostępne w Linq. Co każdy programista powinien wiedzieć o tych dwóch metodach? Na przykład: kiedy używać jednego nad drugim, jakie są zalety używania jednego nad drugim itp.
Select
I Where
metody są dostępne w Linq. Co każdy programista powinien wiedzieć o tych dwóch metodach? Na przykład: kiedy używać jednego nad drugim, jakie są zalety używania jednego nad drugim itp.
Odpowiedzi:
Gdzie
znajduje pasujące elementy i zwraca tylko te, które pasują ( filtrowanie ).
-> IEnumerable<A>
na IEnumerable<A>
zewnątrz
Wybierz
zwraca coś dla wszystkich elementów w źródle ( projekcja / transformacja ). Tym czymś mogą być same przedmioty, ale zazwyczaj są to jakieś projekcje.
-> IEnumerable<A>
na IEnumerable<B>
zewnątrz
Select
zawsze zwróci tę samą liczbę elementów na liście (niezależnie od warunku filtru, który możesz mieć). Where
może zwrócić mniej elementów w zależności od stanu filtra.
Where == filter
iSelect == map
Select i Where to dwa zupełnie różne operatory działające na IEnumerable s.
Pierwszy to tak zwany operator projekcji , a ostatni to operator ograniczeń .
Ciekawym sposobem uzyskania wglądu w zachowanie takich operatorów jest przyjrzenie się ich „typowi funkcjonalnemu”.
Wybierz: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; przyjmuje jako dane wejściowe zarówno IEnumerable zawierające elementy typu T1, jak i funkcję przekształcającą elementy typu T1 na elementy typu T2. Dane wyjściowe to IEnumerable zawierające elementy typu T2.
Na tej podstawie można łatwo zgadnąć, że ten operator wygeneruje dane wyjściowe, stosując funkcję wejściową do każdego elementu wejściowego IEnumerable i zawijając wyniki do nowego IEnumerable.
Za pomocą matematycznej jak notacji trwa na wejściu (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 element IEnumerable zawierający elementy typu T1 i predykat na T1 (to znaczy funkcję, która generuje wynik boolowski dla danych wejściowych typu T1). Widzisz, że dane wyjściowe są również IEnumerable zawierające elementy typu T1.
Tym razem można by się domyślić, że element wejściowy 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ć pewien, że wygeneruje on wynik IEnumerable, pobierając z danych wejściowych tylko te elementy, które są szacowane na true w zastosowaniu predykatu.
Ludzie z doświadczeniem w programowaniu funkcjonalnym zwykle myślą w ten sposób. Pozwala wywnioskować (lub przynajmniej zgadywać ...), co robi operator, tylko patrząc na jego typ!
W ramach ćwiczenia spróbuj spojrzeć na inne operatory wprowadzone przez LINQ na IEnumerables i wydedukować ich zachowanie, zanim przejrzysz dokumentację!
Są różne:
Select
chodzi o transformację .
Where
chodzi o filtrowanie .
Where
~ = Filtruj
Select
~ = Mapa
Obie wraca IEnumerable<T>
Jeśli wiesz, jak zaimplementowali Gdzie i wybierz metody rozszerzeń, możesz przewidzieć, co robi ... Próbowałem zaimplementować gdzie i wybrać metody rozszerzeń ... Możesz na to spojrzeć ...
Gdzie Wdrożenie ::
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 realizację:
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 metod rozszerzeń zaimplementowanych przez Microsoft, ponieważ używają drzew wyrażeń do implementacji tego samego.
W przypadku Select it możesz zmapować do IEnumerable nowej struktury.
A.Select(x=>new X{UID=x.uid, UNAME=x.uname})
//input as [IEnumerable<A>] --------> return output as [IEnumerable<X> ]
Where () działa jako filtr IEnumerable, zwróci wynik na podstawie klauzuli where.
A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] --------> return output as [IEnumerable<A> ]