Os métodos Select
e Where
estão disponíveis no Linq. O que todo desenvolvedor deve saber sobre esses dois métodos? Por exemplo: quando usar um sobre o outro, quaisquer vantagens de usar um sobre o outro, etc.
Os métodos Select
e Where
estão disponíveis no Linq. O que todo desenvolvedor deve saber sobre esses dois métodos? Por exemplo: quando usar um sobre o outro, quaisquer vantagens de usar um sobre o outro, etc.
Respostas:
Onde
localiza itens que correspondem e retorna apenas aqueles que correspondem ( filtragem ).
-> IEnumerable<A>
dentro, IEnumerable<A>
fora
Selecione
retorna algo para todos os itens na fonte ( projeção / transformação ). Que algo pode ser os itens em si, mas geralmente são uma projeção de algum tipo.
-> IEnumerable<A>
dentro, IEnumerable<B>
fora
Select
sempre retornará o mesmo número de elementos na lista (independentemente da condição de filtro que você possa ter). Where
pode retornar menos elementos, dependendo da condição do filtro.
Where == filter
eSelect == map
Selecione e Onde estão dois operadores completamente diferentes atuando em IEnumerable s.
O primeiro é o que chamamos de Operador de Projeção , enquanto o último é um Operador de Restrição .
Uma maneira interessante de entender o comportamento desses operadores é dar uma olhada no seu "tipo funcional".
Selecione: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; toma como entrada um IEnumerable contendo elementos do tipo T1 e uma função que transforma elementos do tipo T1 em elementos do tipo T2. A saída é um IEnumerable contendo elementos do tipo T2.
A partir disso, pode-se adivinhar com facilidade que esse operador produzirá sua saída aplicando a função de entrada em cada elemento da entrada IEnumerable e agrupando os resultados dentro de um novo IEnumerable.
Usando um pouco de matemática-como notação, que toma como entrada (a, b, c, ...): IEnumerable <T1> e f: T1 → T2 e produz (f (a), f (b), f (c) , ...): IEnumerable <T2>
Onde: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; este pega um IEnumerable contendo elementos do tipo T1 e um predicado em T1 (ou seja, uma função que produz um resultado booleano para uma entrada do tipo T1). Você vê que a saída também é um IEnumerable contendo elementos do tipo T1.
Desta vez, seria de supor que um elemento da entrada IEnumerable estará presente na saída IEnumerable, dependendo do resultado da aplicação do predicado ao elemento. Adicionando a isso a semântica do nome do operador, você pode ter certeza de que ele produzirá a saída IEnumerable, retirando da entrada apenas os elementos que são avaliados como verdadeiros na aplicação do predicado.
Pessoas com experiência em programação funcional geralmente pensam assim. Permite deduzir (ou pelo menos adivinhar ...) o que um operador faz apenas olhando seu tipo!
Como exercício, tente examinar outros operadores introduzidos pelo LINQ no IEnumerables e deduzir seu comportamento, antes de examinar a documentação!
Eles são distintos:
Select
é tudo sobre transformação .
Where
é tudo sobre filtragem .
Selecione mapeia um enumerável para uma nova estrutura. Se você executar uma seleção em um IEnumerable, obterá uma matriz com o mesmo número de elementos, mas um tipo diferente, dependendo do mapeamento especificado. Onde filtra o IEnumerable para fornecer um subconjunto do IEnumerable original.
Where
~ = Filtro
Select
~ = Mapa
Ambos retornos IEnumerable<T>
Se você sabe como eles implementaram o Where e selecione os métodos de extensão, você pode prever o que está fazendo ... Tentei implementar o where e selecione os métodos de extensão ... Você pode dar uma olhada nele ...
Onde Implementação ::
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;
}
}
}
Selecione a implementação ::
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 );
}
}
Minha implementação funciona bem para qualquer coleção ... Mas difere dos métodos de extensão implementados pela Microsoft, porque eles usam árvores de expressão para implementar o mesmo.
No caso de Selecionar, você pode mapear para um IEnumerable de uma nova estrutura.
A.Select(x=>new X{UID=x.uid, UNAME=x.uname})
//input as [IEnumerable<A>] --------> return output as [IEnumerable<X> ]
Where () funciona como um filtro para o IEnumerable, ele retornará o resultado com base na cláusula where.
A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] --------> return output as [IEnumerable<A> ]