2009-07-31 20 views
91

Los métodos Select y Where están disponibles en Linq. ¿Qué debería saber todo desarrollador sobre estos dos métodos? Por ejemplo: cuándo usar uno sobre el otro, ventajas de usar uno sobre el otro, etc.Linq: ¿Cuál es la diferencia entre Seleccionar y Dónde

+5

No creo que esta pregunta deba marcarse como CW, posiblemente podría tener una respuesta definitiva. – Brandon

+1

@Brandon no hay nada de malo en marcar algo CW si es objetivo. –

+0

@Rex, estoy de acuerdo. Solo digo que la diferencia entre Seleccionar y Dónde tiene una respuesta definitiva, y que la segunda parte de la pregunta probablemente se base en prácticas comúnmente aceptadas. Solo lo señalé en caso de que OP no estuviera seguro de marcar cosas como CW. Si él tuvo la intención de que fuera CW, entonces estoy bien por mí. – Brandon

Respuesta

90

Dónde

Devuelve los elementos que coincidan y sólo devuelve los que lo hacen (filtrado).

->IEnumerable<A> en, IEnumerable<A> cabo

Seleccionar

vuelve algo para todos elementos del origen de la proyección (/transformación). Ese algo podría ser los artículos mismos, pero generalmente son una especie de proyección.

->IEnumerable<A> en, IEnumerable<B> cabo

+5

'Seleccionar' siempre devolverá el mismo número de elementos en la lista (independientemente de las condiciones de filtro que pueda tener). 'Where' puede devolver menos elementos dependiendo de su condición de filtro. –

+0

Y [aquí] (https://msdn.microsoft.com/en-us/library/bb548891 (v = vs.110) .aspx) es un ejemplo de MSDN de 'seleccionar' y [aquí] (https: // msdn.microsoft.com/en-us/library/bb534803(v=vs.110).aspx) es uno para 'where' – yazanpro

+0

Al menos para mí, teniendo algunos antecedentes con otros idiomas, ayuda a pensar que' 'Donde == filter'' y '' Select == map'' – bgusach

15

Seleccione asigna un enumerable a una nueva estructura. Si realiza una selección en un IEnumerable, obtendrá una matriz con el mismo número de elementos, pero un tipo diferente dependiendo de la asignación que haya especificado. Donde filtra IEnumerable para que le dé un subconjunto del IEnumerable original.

33

Son distintos:

Select tiene que ver con la transformación .

Where Todo és sobre filtering.

37

Seleccionar y Dónde son dos operadores completamente diferentes que actúan sobre IEnumerable s.

El primero de ellos es lo que llamamos un operador de proyección , mientras que el último es un operador restricción.

Una forma interesante de tener una idea del comportamiento de tales operadores es echar un vistazo a su "tipo funcional".

  • Select: (IEnumerable < T1>, Func < T1, T2>) → IEnumerable < T2>; toma como entrada tanto un elemento IEnumerable que contiene elementos de tipo T1 como una función que transforma elementos de tipo T1 en elementos de tipo T2. La salida es un IEnumerable que contiene elementos de tipo T2.

    De esto, uno puede adivinar fácilmente que este operador producirá su salida aplicando la función de entrada en cada elemento de la entrada IEnumerable, y envolviendo los resultados dentro de un nuevo IEnumerable.

    Usando alguna notación matemática, toma como entrada (a, b, c, ...): IEnumerable < T1> y f: T1 T2 → y produce (f (a), f (b), f (c), ...): IEnumerable < T2>

  • Donde: (IEnumerable < T1>, Func < T1, bool>) → IEnumerable < T1>; este toma un IEnumerable que contiene elementos de tipo T1 y un predicado en T1 (es decir, una función que produce un resultado booleano para una entrada de tipo T1). Verá que el resultado también es un IEnumerable que contiene elementos del tipo T1.

    Esta vez uno supondría que un elemento de la entrada IEnumerable estará presente en la salida IEnumerable dependiendo del resultado de la aplicación del predicado al elemento. Agregando a esto la semántica del nombre del operador, puede estar seguro de que producirá la salida IEnumerable tomando de la entrada solo los elementos que se evalúan como verdaderos en la aplicación del predicado.

Las personas con conocimientos de programación funcional por lo general piensan de esta manera. Le permite deducir (o al menos adivinar ...) lo que hace un operador solo al mirar su tipo.

Como ejercicio, intente observar a otros operadores introducidos por LINQ en IEnumerables y deduzca su comportamiento antes de consultar la documentación.

6

Si sabe cómo han implementado Dónde y seleccione los métodos de extensión, puede predecir lo que está haciendo ... Intenté implementar dónde y seleccionar los métodos de extensión ... Puede echarle un vistazo ...

Cuando para la ejecución ::

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; 
     } 
    } 
} 

Seleccionar aplicación ::

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); 
    } 
} 

Mi aplicación funciona bien para cualquier colección .. Pero difiere de los métodos de extensión implementados por Microsoft, porque usan árboles de expresión para implementar lo mismo.

Cuestiones relacionadas