Differenza tra Select e ConvertAll in C #


117

Ho qualche lista:

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

Voglio applicare alcune trasformazioni agli elementi del mio elenco. Posso farlo in due modi:

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

Qual è la differenza tra questi due modi?


16
Non è necessario .ToList () dopo ConvertAll ().
Gleno

mai sentito parlare di ConvertAll, ho conosciuto qualcosa di nuovo oggi
Amit Bisht

Risposte:


117

Selectè un metodo di estensione LINQ e funziona su tutti gli IEnumerable<T>oggetti mentre ConvertAllè implementato solo da List<T>. Il ConvertAllmetodo esiste da .NET 2.0 mentre LINQ è stato introdotto con 3.5.

Si dovrebbe favorire Selectpiù di ConvertAllcome funziona per qualsiasi tipo di lista, ma lo fanno lo stesso in fondo.


7
E per quanto riguarda le esibizioni? Se ho un elenco, è più efficiente utilizzare ConvertAll o Select?
Nicolas

@Nicolas: il tempo di esecuzione totale è più o meno lo stesso, ma elaborano in modo diverso, quindi si adattano a diverse situazioni. Ho aggiunto qualcosa al riguardo nella mia risposta.
Guffa

3
Non puoi confrontare Selecte ConvertAll. Il primo seleziona ogni elemento in una sequenza e sei libero di fare quello che vuoi con esso. Quest'ultimo ha una chiara intenzione: convertire questo oggetto in qualcos'altro.
Tim Schmelter

1
È interessante notare che la classe List <T> contiene diversi metodi con corrispondenze quasi esatte in LINQ. Exists -> Any, Find -> First, FindAll -> Where, FindLast -> Last, TrueForAll -> All
Mikal Schacht Jensen

La differenza tra ConvertAll e Select è ConvertAll assegnerà anticipatamente la dimensione dell'elenco. Per una grande sequenza questo farà la differenza nelle prestazioni. Quindi, se il tuo obiettivo è la prestazione, usa ConvertAll. Se le prestazioni non sono un problema, utilizzare Seleziona poiché è più idiomatico nella lingua e indica che le prestazioni dei lettori futuri non erano un problema.
Durdsoft il

82

ConvertAllnon è un'estensione, è un metodo nella classe list. Non è necessario richiamare ToListil risultato poiché è già un elenco:

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

Quindi, la differenza è che il ConvertAllmetodo può essere utilizzato solo su un elenco e restituisce un elenco. Il Selectmetodo può essere utilizzato su qualsiasi raccolta che implementa l' IEnumerable<T>interfaccia e restituisce un file IEnumerable<T>.

Inoltre, eseguono l'elaborazione in modo diverso, quindi hanno i loro punti di forza in diverse situazioni. Il ConvertAllmetodo scorre l'elenco e crea un nuovo elenco in una volta sola, mentre il Selectmetodo utilizza un'esecuzione lenta ed elabora gli elementi solo quando ne hai bisogno. Se non hai bisogno di tutto l'articolo, il Selectmetodo è più efficiente. D'altra parte, una volta ConvertAllrestituito l'elenco, non è necessario mantenere l'elenco originale.


Probabilmente, non si deve mai "mantenere l'elenco originale": sarà fatto come necessario dal GC.
user2864740

8
@ user2864740: Sì, è vero se la fonte è strettamente un elenco in memoria. Se viene letto, ad esempio, da un file, è necessario tenerlo aperto finché non si è elaborato il risultato dal file Select.
Guffa

19

La prima risposta non dovrebbe essere quella accettata. Sono un ex MVP Microsoft C # 2007.

In contrasto con la risposta accettata, ConvertAllè molto più efficiente della combinazione di Selecte ToList().

Prima di tutto, ConvertAllè strettamente più veloce e utilizza la quantità minima di memoria per farlo. Uguale a Array.ConvertAll vs Select e ToArray. Questo sarebbe molto più evidente con un array di lunghezza maggiore o molte chiamate all'interno di un ciclo.

1) ConvertAllconosce la dimensione dell'elenco finale ed evita di riallocare l'array di base. ToList() continuerà a ridimensionare l'array più volte.

2) ToListeffettuerà IEnumerable<>chiamate all'interfaccia più lente , mentre ConvertAlleseguirà un ciclo attraverso l'array sottostante senza chiamate aggiuntive o controlli di intervallo.

3) Seleziona creerà un IEnumerable<T>oggetto aggiuntivo .


1

So che è un po 'tardi, ma ho ancora aggiunto perché questo potrebbe essere di qualche utilità per altri in futuro.

Quando lo si utilizza nell'espressione di query EntityFramework, non è consigliabile utilizzare ConvertAll () poiché valuta l'espressione piuttosto che lasciarla come espressione per un utilizzo futuro. Ciò degrada seriamente le prestazioni di esecuzione delle query del database poiché dovrebbe effettuare un numero di chiamate prima di valutare l'espressione finale.


9
Non proprio. Come fa notare Guffa in questa risposta , ConvertAll è un metodoList<T> . Con il tempo che avete la lista, hai già valutati la tua espressione. Ma hai ragione - se non vuoi valutare tutto, Selectè preferibile.
Wai Ha Lee
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.