Los operadores de elemento son todos aquellos métodos extensores dentro de la
librería de LinQ, que devuelven una
única pieza o el valor por defecto de su tipo a partir de una secuencia de
datos IEnumerable<TSource>.
Estos operadores suelen estar compuestos por su definición
simple y una variación ‘OrDefault’.
Esta variación ‘OrDefault’, viene a
significar, que en caso de no cumplirse el criterio de búsqueda, el operador no
lanzará ninguna excepción y devolverá
el valor por defecto del tipo
al que pertenece la secuencia. Este valor por defecto es el que devolvería el
operador default(T),
que ya estudiamos con anterioridad.
Recuerda que aquí tienes el indice de todos los posts del Curso de LinQ.
ElementAt
y ElementAtOrDefault, son unos
operadores que devuelven el elemento situado en la posición que marca su parámetro.
Este parámetro es un int
de índice 0.
En caso de indicar un índice negativo, o un índice superior al nº de elementos que contiene
la secuencia, se lanzará una excepción de tipo ArgumentOutOfRangeException, siempre y cuando estemos
utilizando el operador ElementAt,
si elegimos la opción de ElementAtOrDefault,
el método nos devolverá el valor por defecto default(T)
del tipo de datos que esté compuesto la colección.
Estas son las firmas de sus métodos extensores:
A simple vista puede parecer que no tienen mucha utilidad,
ya que normalmente solemos trabajar con colecciones que implementan la interfaz
IList y está activa el uso de
indexadores a través de los corchetes
‘[]’, pero cuando trabajamos directamente con IEnumerables<TSource>, y con ejecución diferida, no
tenemos disponible esta posibilidad y este operador se vuelve prácticamente
indispensable.
Como podemos observar, a la hora de filtrar la operación, no
hacemos uso del operador ToList(),
que obligaría a realizar la ejecución en el momento, por lo que efectuaremos ejecución
diferida y el filtrado no se ejecutará hasta que estemos dentro del bucle For. El tipo de devolución será un IEnumerable<Automovil> y este tipo
no tiene posibilidad de indexadores, y el único medio de acceder a sus
elementos por índice sería mediante el operador ElementAt.
First y FirstOrDefault
Estos dos operadores devuelven el primer elemento de una
colección.
Tienen 2 sobrecargas, una en la que no recibe ningún tipo de
parámetro y otra en la que recibe un parámetro de tipo Func<TSource, bool> que realizará un filtrado inicial de
los datos, y se quedará con el primer elemento del resultado del filtrado:
Estas son las firmas de sus métodos extensores:
En caso de que la colección esté vacía, si utilizamos el
método First, se lanzará una
excepción del tipo InvalidOperationException.
Para evitarlo, como en los casos anteriores utilizar FirstOrDefault.
Muy sencillo, al principio seleccionamos el primer elemento
con el operador First, ya que estamos
seguros que la lista contiene elementos. Después, hacemos algo pseudo
aleatorio, comprobando si el segundo actual de la fecha del sistema es par, en ese caso, limpiamos la colección,
en caso contrario la dejamos igual. Para este caso estamos obligados a utilizar
FirstOrDefault, ya que no tenemos la
certeza que nuestra secuencia contenga elementos. Para acabar, impresión en la consola y poco más.
Resultado de la ejecución cuando el segundo es par:
Ahora la otra opción:
NOTA:
En esta parte tengo que hacer un apunte de un buen uso de LinQ, poniendo un ejemplo que
normalmente solemos realizar para buscar un elemento en concreto dentro de una
colección:
Realizados un filtrado por un criterio y después llamamos a FirstOrDefault, para quedarnos con
la primera pieza. Esta acción no es todo lo óptima que debiera, y no utiliza
toda la potencia de LinQ,
ya que primero efectúa el filtrado y luego se queda con la primera operación.
Para elaborar esto, utilizamos la segunda sobrecarga de First y FirstOrDefault,
que confecciona todo esta tarea, escribiendo menos código y trabajando a bajo
nivel. Así sería:
Last y LastOrDefault
Pues para no soltar mucho más rollo, ni alargar esto por
alargar, de los operadores Last
y LastOrDefault, solo hay que añadir
que son exactamente iguales a los dos anteriores (First y FirstOrDefault)
pero en vez de devolver el primer
elemento, devolviendo el último.
Single y SingleOrDefault
Los operadores Single
y SingleOrDefault, son bastante más
restrictivos que los anteriores y obligan a que la secuencia o el resultado del
predicado facilitado a la secuencia sea de un único elemento. En el caso de Single, si la colección o el
predicado de resultado devuelven un número de elementos diferente a 1, ósea, 0, 2, 3, …, n, se lanzará un InvalidOperationException. En el caso de SingleOrDefault, si la colección o el resultado del predicado retornan
0 elementos, este como en los casos
anteriores de ‘OrDefault’ reintegrará
el valor por defecto default(T)
de TSource, si el resultado es mayor de
1, el proceso será el mismo que con
su hermano Single y lanzará un InvalidOperationException.
Estos operadores también tienen 2 sobrecargas cada uno, una
inicial que no recibe ningún parámetro y otra que recibe como viene siendo
normal en estos casos un Func<TSource,
bool> llamado Predicate.
Estas son las firmas de sus métodos extensores:
Vamos ahora a ver un ejemplo en código:
DefaultIfEmpty
Este operador, nos permite añadir un elemento a nuestra
secuencia, en caso de que esta esté vacía, vamos que posea 0 items. Tiene 2
sobrecargas, una que recibe parámetros y que añadiría un elemento del tipo default(TSource), y otra que nos
permite añadir el valor que contendrá por defecto.
Estas son las firmas de sus sobrecargas:
Vamos a ver lo que nos gusta, el código:
Resultado:
Como podemos observar, en cada una de las ejecuciones de las
dos sobrecargas, las secuencias de resultado solo tienen un elemento. En el
primer caso, con el valor ‘null’,
que es el valor por defecto del tipo Automovil
y en el segundo, un valor por
defecto personalizado que le indicamos en el parámetro.
No hay comentarios :
Publicar un comentario