Différence entre Select et ConvertAll en C #

117

J'ai une liste:

List<int> list = new List<int> { 1, 2, 3, 4, 5 };

Je souhaite appliquer une transformation aux éléments de ma liste. Je peux le faire de deux manières:

List<int> list1 = list.Select(x => 2 * x).ToList();
List<int> list2 = list.ConvertAll(x => 2 * x).ToList();

Quelle est la différence entre ces deux méthodes?

AndreyAkinshin
la source
16
Vous n'avez pas besoin de .ToList () après ConvertAll ().
Gleno
jamais entendu parler de ConvertAll, j'ai appris quelque chose de nouveau aujourd'hui
Amit Bisht

Réponses:

117

Selectest une méthode d'extension LINQ et fonctionne sur tous les IEnumerable<T>objets alors qu'elle ConvertAlln'est implémentée que par List<T>. La ConvertAllméthode existe depuis .NET 2.0 alors que LINQ a été introduit avec 3.5.

Vous devriez privilégier Selectplus ConvertAllque cela fonctionne pour tout type de liste, mais ils faire la même chose au fond.

Oliver Hanappi
la source
7
Et qu'en est-il des performances? Si j'ai une liste, est-il plus performant d'utiliser ConvertAll ou Select?
Nicolas
@Nicolas: Le temps d'exécution total est à peu près le même, mais ils font le traitement différemment pour s'adapter à différentes situations. J'en ai ajouté dans ma réponse.
Guffa
3
Vous ne pouvez pas comparer Selectet ConvertAll. Le premier sélectionne chaque élément dans une séquence et vous êtes libre d'en faire ce que vous voulez. Ce dernier a une intention claire: convertir cet objet en autre chose.
Tim Schmelter
1
Fait intéressant, la classe List <T> contient plusieurs méthodes qui ont des correspondances presque exactes dans LINQ. Existe -> Any, Find -> First, FindAll -> Where, FindLast -> Last, TrueForAll -> All
Mikal Schacht Jensen
La différence entre ConvertAll et Select est que ConvertAll attribuera la taille de la liste à l'avance. Pour une grande séquence, cela fera une différence de performance. Ainsi, si la performance est votre objectif, utilisez ConvertAll. Si les performances ne sont pas un problème, utilisez Select car il est plus idiomatique dans la langue et indique que les performances des futurs lecteurs ne sont pas un problème.
Durdsoft
82

ConvertAlln'est pas une extension, c'est une méthode de la classe list. Vous n'êtes pas obligé d'appeler ToListle résultat car c'est déjà une liste:

List<int> list2 = list.ConvertAll(x => 2 * x);

Donc, la différence est que la ConvertAllméthode ne peut être utilisée que sur une liste et qu'elle renvoie une liste. La Selectméthode peut être utilisée sur n'importe quelle collection qui implémente l' IEnumerable<T>interface et elle renvoie un IEnumerable<T>.

En outre, ils effectuent le traitement différemment, de sorte qu'ils ont leurs forces dans différentes situations. La ConvertAllméthode parcourt la liste et crée une nouvelle liste en une seule fois, tandis que la Selectméthode utilise une exécution différée et ne traite que les éléments dont vous avez besoin. Si vous n'avez pas besoin de tous les éléments, la Selectméthode est plus efficace. Par contre, une fois ConvertAllla liste renvoyée, vous n'avez pas besoin de conserver la liste d'origine.

Guffa
la source
On peut soutenir qu'il n'est jamais nécessaire de «conserver la liste originale»: cela sera fait au besoin par le GC.
user2864740
8
@ user2864740: Oui, c'est vrai si la source est strictement une liste en mémoire. S'il est lu par exemple à partir d'un fichier, vous devez garder le fichier ouvert jusqu'à ce que vous ayez traité le résultat du fichier Select.
Guffa
19

La première réponse ne doit pas être celle acceptée. Je suis un ancien MVP C # Microsoft 2007.

Contrairement à la réponse acceptée, ConvertAllest beaucoup plus efficace que la combinaison de Selectet ToList().

Tout d'abord, ConvertAllest strictement plus rapide et utilise le minimum de mémoire pour ce faire. Identique à Array.ConvertAll vs Select et ToArray. Ce serait beaucoup plus évident avec un tableau de plus grande longueur ou de nombreux appels dans une boucle.

1) ConvertAllconnaît la taille de la liste finale et évite de réallouer le tableau de base. ToList() continuera à redimensionner le tableau plusieurs fois.

2) ToListfera des IEnumerable<>appels d' interface plus lents , tandis que ConvertAllbouclera à travers le tableau sous-jacent sans appels supplémentaires ni vérification de plage.

3) Select créera un IEnumerable<T>objet supplémentaire .

Wesner Moise
la source
1

Je sais que c'est un peu tard mais j'ai quand même ajouté car cela pourrait être d'une certaine utilité pour d'autres à l'avenir.

Lorsque vous l'utilisez dans une expression de requête EntityFramework, il n'est pas recommandé d'utiliser ConvertAll () car il évalue l'expression plutôt que de la laisser comme expression pour une utilisation future. Cela dégrade gravement les performances d'exécution des requêtes de base de données car il faudrait effectuer un certain nombre d'appels avant d'évaluer l'expression finale.

Navap
la source
9
Pas assez. Comme le souligne Guffa dans cette réponse , ConvertAll est une méthode surList<T> . Au moment où vous avez la liste, vous avez déjà évalué votre expression. Mais vous avez raison - si vous ne voulez pas tout évaluer, Selectc'est préférable.
Wai Ha Lee