Les méthodes Select
et Where
sont disponibles dans Linq. Que doit savoir chaque développeur sur ces deux méthodes? Par exemple: quand utiliser l'un par rapport à l'autre, les avantages de l'utilisation de l'un par rapport à l'autre, etc.
Les méthodes Select
et Where
sont disponibles dans Linq. Que doit savoir chaque développeur sur ces deux méthodes? Par exemple: quand utiliser l'un par rapport à l'autre, les avantages de l'utilisation de l'un par rapport à l'autre, etc.
Réponses:
Où
trouve les éléments qui correspondent et ne renvoie que ceux qui le font ( filtrage ).
-> IEnumerable<A>
in, IEnumerable<A>
out
Sélectionner
renvoie quelque chose pour tous les éléments de la source ( projection / transformation ). Ce quelque chose pourrait être les éléments eux-mêmes, mais il s'agit plus généralement d'une projection.
-> IEnumerable<A>
in, IEnumerable<B>
out
Select
renverra toujours le même nombre d'éléments dans la liste (quelle que soit la condition de filtre que vous pourriez avoir). Where
peut renvoyer moins d'éléments en fonction de la condition de votre filtre.
Where == filter
etSelect == map
Select et Where sont deux opérateurs complètement différents agissant sur les IEnumerable s.
Le premier est ce que nous appelons un opérateur de projection , tandis que le dernier est un opérateur de restriction .
Une manière intéressante d'avoir un aperçu du comportement de ces opérateurs est de regarder leur "type fonctionnel".
Sélectionnez: (IEnumerable <T1>, Func <T1, T2>) → IEnumerable <T2> ; il prend en entrée à la fois un IEnumerable contenant des éléments de type T1 et une fonction transformant des éléments de type T1 en éléments de type T2. La sortie est un IEnumerable contenant des éléments de type T2.
À partir de là, on peut facilement deviner que cet opérateur produira sa sortie en appliquant la fonction d'entrée sur chaque élément de l'entrée IEnumerable et en enveloppant les résultats dans un nouveau IEnumerable.
En utilisant une notation de type mathématique, il prend comme entrée (a, b, c, ...): IEnumerable <T1> et f: T1 → T2 et produit (f (a), f (b), f (c) , ...): IEnumerable <T2>
Où: (IEnumerable <T1>, Func <T1, bool>) → IEnumerable <T1> ; celui-ci prend un IEnumerable contenant des éléments de type T1 et un prédicat sur T1 (c'est-à-dire une fonction qui produit un résultat booléen pour une entrée de type T1). Vous voyez que la sortie est également un IEnumerable contenant des éléments de type T1.
Cette fois, on devinerait qu'un élément de l'entrée IEnumerable sera présent sur la sortie IEnumerable en fonction du résultat de l'application du prédicat à l'élément. En ajoutant à cela la sémantique du nom de l'opérateur, vous pouvez être sûr qu'il produira la sortie IEnumerable en prenant de l'entrée un uniquement les éléments dont la valeur est vraie sur l'application du prédicat.
Les personnes ayant une formation en programmation fonctionnelle pensent généralement comme ça. Cela permet de déduire (ou du moins de deviner ...) ce que fait un opérateur uniquement en regardant son type!
En guise d'exercice, essayez de regarder d'autres opérateurs introduits par LINQ sur IEnumerables et en déduire leur comportement, avant de consulter la documentation!
Ils sont distincts:
Select
est une question de transformation .
Where
est une question de filtrage .
Select mappe un énumérable à une nouvelle structure. Si vous effectuez une sélection sur un IEnumerable, vous obtiendrez un tableau avec le même nombre d'éléments, mais un type différent selon le mappage que vous avez spécifié. Où filtre le IEnumerable afin qu'il vous donne un sous-ensemble du IEnumerable d'origine.
Where
~ = Filtre
Select
~ = Carte
Les deux retours IEnumerable<T>
Si vous savez comment ils ont implémenté Where et sélectionnez des méthodes d'extension, vous pouvez prédire ce qu'il fait ... J'ai essayé d'implémenter où et de sélectionner des méthodes d'extension ... Vous pouvez y jeter un œil ...
Où la mise en œuvre:
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;
}
}
}
Sélectionnez l'implémentation ::
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 );
}
}
Mon implémentation fonctionne bien pour n'importe quelle collection ... Mais elle diffère des méthodes d'extension implémentées par Microsoft, car elles utilisent des arbres d'expression pour implémenter la même chose.
Dans le cas de Select it, vous pouvez mapper à un IEnumerable d'une nouvelle structure.
A.Select(x=>new X{UID=x.uid, UNAME=x.uname})
//input as [IEnumerable<A>] --------> return output as [IEnumerable<X> ]
Where () fonctionne comme un filtre pour IEnumerable, il retournera le résultat sur la base de la clause where.
A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] --------> return output as [IEnumerable<A> ]