Diferencia entre Select y ConvertAll en C #

117

Tengo alguna lista:

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

Quiero aplicar alguna transformación a los elementos de mi lista. Puedo hacer esto de dos formas:

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

¿Cuál es la diferencia entre estas dos formas?

Andrey Akinshin
fuente
16
No necesita .ToList () después de ConvertAll ().
Gleno
nunca escuché de ConvertAll, conocí algo nuevo hoy
Amit Bisht

Respuestas:

117

Selectes un método de extensión LINQ y funciona en todos los IEnumerable<T>objetos, mientras ConvertAllque solo lo implementa List<T>. El ConvertAllmétodo existe desde .NET 2.0, mientras que LINQ se introdujo con 3.5.

Usted debe favorecer Selectmás ConvertAll, ya que funciona para cualquier tipo de lista, pero lo hacen básicamente el mismo.

Oliver Hanappi
fuente
7
¿Y las actuaciones? Si tengo una lista, ¿es más eficaz utilizar ConvertAll o Select?
Nicolas
@Nicolas: El tiempo total de ejecución es aproximadamente el mismo, pero hacen el procesamiento de manera diferente para que se adapten a diferentes situaciones. Agregué algo al respecto en mi respuesta.
Guffa
3
No se puede comparar Selecty ConvertAll. El primero selecciona cada elemento en una secuencia y usted es libre de hacer lo que quiera con él. Este último tiene una intención clara: convertir este artículo en otra cosa.
Tim Schmelter
1
Curiosamente, la clase List <T> contiene varios métodos que tienen coincidencias casi exactas en LINQ. Exists -> Any, Find -> First, FindAll -> Where, FindLast -> Last, TrueForAll -> All
Mikal Schacht Jensen
La diferencia entre ConvertAll y Select es que ConvertAll asignará el tamaño de la lista de antemano. Para una secuencia grande, esto marcará una diferencia de rendimiento. Por lo tanto, si su objetivo es el rendimiento, use ConvertAll. Si el rendimiento no es un problema, use Select, ya que es más idiomático en el idioma y le dice a los futuros lectores que el rendimiento no fue un problema.
Durdsoft
82

ConvertAllno es una extensión, es un método en la clase list. No tiene que llamar ToListal resultado porque ya es una lista:

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

Entonces, la diferencia es que el ConvertAllmétodo solo se puede usar en una lista y devuelve una lista. El Selectmétodo se puede utilizar en cualquier colección que implemente la IEnumerable<T>interfaz y devuelve un IEnumerable<T>.

Además, hacen el procesamiento de manera diferente, por lo que tienen sus puntos fuertes en diferentes situaciones. El ConvertAllmétodo recorre la lista y crea una nueva lista de una sola vez, mientras que el Selectmétodo utiliza la ejecución diferida y solo procesa los elementos cuando los necesita. Si no necesita todo el artículo, el Selectmétodo es más eficiente. Por otro lado, una vez que ConvertAllhaya devuelto la lista, no es necesario que conserve la lista original.

Guffa
fuente
Podría decirse que uno nunca tiene que "mantener la lista original": el CG lo hará según sea necesario.
user2864740
8
@ user2864740: Sí, eso es cierto si la fuente es estrictamente una lista en la memoria. Si se lee, por ejemplo, de un archivo, entonces debe mantener el archivo abierto hasta que haya procesado el resultado del Select.
Guffa
19

La primera respuesta no debería ser la aceptada. Soy un ex MVP de Microsoft C # 2007.

En contraste con la respuesta aceptada, ConvertAlles mucho más eficiente que la combinación de Selecty ToList().

En primer lugar, ConvertAlles estrictamente más rápido y utiliza la cantidad mínima de memoria para hacerlo. Igual que Array.ConvertAll vs Select y ToArray. Esto sería mucho más evidente con una matriz de mayor longitud o muchas llamadas dentro de un bucle.

1) ConvertAllconoce el tamaño de la lista final y evita reasignar la matriz base. ToList() seguirá cambiando el tamaño de la matriz varias veces.

2) ToListhará IEnumerable<>llamadas de interfaz más lentas , mientras ConvertAllque recorrerá la matriz subyacente sin llamadas adicionales o comprobaciones de rango.

3) Seleccionar creará un IEnumerable<T>objeto adicional .

Wesner Moise
fuente
1

Sé que esto es un poco tarde, pero aún lo he agregado porque esto podría ser de alguna utilidad para otros en el futuro.

Cuando se usa en la expresión de consulta EntityFramework, no se recomienda usar ConvertAll () ya que evalúa la expresión en lugar de dejarla como expresión para uso futuro. Esto degrada seriamente el rendimiento de ejecución de la consulta de la base de datos, ya que tendría que realizar un número de llamadas antes de evaluar la expresión final.

Navap
fuente
9
No exactamente. Como señala Guffa en esta respuesta , ConvertAll es un métodoList<T> . Para cuando tenga la lista, ya habrá evaluado su expresión. Pero tienes razón: si no quieres evaluar todo, Selectes preferible.
Wai Ha Lee