Unterschied zwischen Select und ConvertAll in C #

117

Ich habe eine Liste:

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

Ich möchte eine Transformation auf Elemente meiner Liste anwenden. Ich kann dies auf zwei Arten tun:

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

Was ist der Unterschied zwischen diesen beiden Möglichkeiten?

AndreyAkinshin
quelle
16
Sie müssen nicht .ToList () nach ConvertAll ().
Gleno
Ich habe noch nie von ConvertAll gehört und heute etwas Neues kennengelernt
Amit Bisht

Antworten:

117

Selectist eine LINQ-Erweiterungsmethode und funktioniert für alle IEnumerable<T>Objekte, während ConvertAllsie nur von implementiert wird List<T>. Die ConvertAllMethode existiert seit .NET 2.0, während LINQ mit 3.5 eingeführt wurde.

Sie sollten bevorzugen Selectüber , ConvertAllwie es für jede Art von Liste funktioniert, aber sie denselben im Grunde tun.

Oliver Hanappi
quelle
7
Und was ist mit den Auftritten? Wenn ich eine Liste habe, ist es leistungsfähiger, ConvertAll oder Select zu verwenden?
Nicolas
@Nicolas: Die Gesamtausführungszeit ist ungefähr gleich, aber die Verarbeitung erfolgt unterschiedlich, sodass sie für unterschiedliche Situationen geeignet sind. Ich habe in meiner Antwort einige dazu hinzugefügt.
Guffa
3
Sie können nicht vergleichen Selectund ConvertAll. Ersteres wählt jedes Element in einer Sequenz aus und Sie können damit tun, was Sie wollen. Letzteres hat eine klare Absicht: diesen Gegenstand in etwas anderes umwandeln.
Tim Schmelter
1
Interessanterweise enthält die List <T> -Klasse mehrere Methoden, die in LINQ fast exakte Übereinstimmungen aufweisen. Existiert -> Any, Find -> First, FindAll -> Where, FindLast -> Last, TrueForAll -> All
Mikal Schacht Jensen
Der Unterschied zwischen ConvertAll und Select besteht darin, dass ConvertAll die Größe der Liste vorab zuweist. Bei einer großen Sequenz macht dies einen Leistungsunterschied. Wenn Sie also Leistung anstreben, verwenden Sie ConvertAll. Wenn die Leistung kein Problem darstellt, verwenden Sie Select, da sie in der Sprache idiomatischer ist und den zukünftigen Lesern mitteilt, dass die Leistung kein Problem darstellt.
Durdsoft
82

ConvertAllist keine Erweiterung, sondern eine Methode in der Listenklasse. Sie müssen ToListdas Ergebnis nicht aufrufen, da es bereits eine Liste ist:

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

Der Unterschied besteht also darin, dass die ConvertAllMethode nur für eine Liste verwendet werden kann und eine Liste zurückgibt. Die SelectMethode kann für jede Sammlung verwendet werden, die die IEnumerable<T>Schnittstelle implementiert , und gibt eine zurück IEnumerable<T>.

Außerdem verarbeiten sie die Verarbeitung unterschiedlich, sodass sie ihre Stärken in unterschiedlichen Situationen haben. Die ConvertAllMethode durchläuft die Liste und erstellt auf einmal eine neue Liste, während die SelectMethode die verzögerte Ausführung verwendet und die Elemente nur nach Bedarf verarbeitet. Wenn Sie nicht alle Elemente benötigen, ist die SelectMethode effizienter. Auf der anderen Seite, einmal ConvertAllhat die Liste zurückgegeben, müssen Sie nicht die ursprüngliche Liste zu halten.

Guffa
quelle
Wohl muss man nie "die ursprüngliche Liste behalten": Sie wird nach Bedarf vom GC durchgeführt.
user2864740
8
@ user2864740: Ja, das ist wahr, wenn die Quelle ausschließlich eine Liste im Speicher ist. Wenn es beispielsweise aus einer Datei gelesen wird, müssen Sie die Datei geöffnet lassen, bis Sie das Ergebnis aus der Datei verarbeitet haben Select.
Guffa
19

Die erste Antwort sollte nicht die akzeptierte sein. Ich bin ein ehemaliger 2007 C # Microsoft MVP.

Im Gegensatz zur akzeptierten Antwort ConvertAllist es viel effizienter als die Kombination von Selectund ToList().

Erstens ConvertAllist es streng schneller und es verwendet die minimale Menge an Speicher, um dies zu tun. Entspricht Array.ConvertAll vs Select und ToArray. Dies wäre bei einem Array mit größerer Länge oder vielen Aufrufen innerhalb einer Schleife viel offensichtlicher.

1) ConvertAllkennt die Größe der endgültigen Liste und vermeidet die Neuzuweisung des Basisarrays. ToList() ändert die Größe des Arrays mehrmals.

2) ToListführt langsamere Schnittstellenaufrufe durch IEnumerable<>, während ConvertAlldas zugrunde liegende Array ohne zusätzliche Aufrufe oder Bereichsprüfungen durchlaufen wird.

3) Mit Auswahl wird ein zusätzliches IEnumerable<T>Objekt erstellt.

Wesner Moise
quelle
1

Ich weiß, dass dies etwas spät ist, aber ich habe noch hinzugefügt, weil dies in Zukunft für andere von Nutzen sein könnte.

Wenn Sie es im EntityFramework-Abfrageausdruck verwenden, wird nicht empfohlen, ConvertAll () zu verwenden, da es den Ausdruck auswertet, anstatt ihn als Ausdruck für die zukünftige Verwendung zu belassen. Dies beeinträchtigt die Ausführungsleistung von Datenbankabfragen erheblich, da vor der Auswertung des endgültigen Ausdrucks die Anzahl der Aufrufe erfolgen müsste.

Navap
quelle
9
Nicht ganz. Wie Guffa in dieser Antwort hervorhebt , ConvertAll handelt es sich um eine MethodeList<T> . Bis Sie haben die Liste, haben Sie bereits Ihren Ausdruck ausgewertet. Aber Sie haben Recht - wenn Sie nicht alle bewerten möchten, Selectist dies vorzuziehen.
Wai Ha Lee