Como su propio nombre indica, los operadores de conversión
realizan transformaciones de datos de un tipo de colecciones a otras.
En este caso tenemos un grupo de operadores de conversión
que son de ejecución instantánea, compuesta por los operadores ToList, ToArray, ToLookUp
y ToDictionary, y otro grupo de carga
perezosa o diferida, compuesta por OffType
y Cast. De este último tipo también
sería el operador AsEnumerable,
pero en éste no pondremos mucho énfasis, ya que es un operador que se utiliza
más en LinqToSql o LinqToEntities, y este curso es de LinqToObjects.
Recuerda que aquí tienes el indice de todos los posts del Curso de LinQ.
Vamos con una de las entradas más sencillas de todas las que
hemos visto hasta ahora.
AsEnumerable
El operador AsEnumerable,
recibe una secuencia de tipo IEnumerable<T>,
para devolver otra de IEnumerable<T>.
Esto puede parecer una tontería si lo miramos de forma literal, ya que
podríamos pensar que toma un objeto de un tipo para devolver el mismo objeto,
pero no es exactamente así, ya que el tipo extensor inicial de su parámetro, no
tiene por qué ser de tipo IEnumerable<T>
estrictamente, puede ser de cualquier tipo que implemente esta interfaz.
Su firma:
Como hemos comentado en la introducción, en la práctica,
este operador suele utilizarse solo entre conversiones de tipo IQueriable<T> a IEnumerable<T>, para
transformaciones de operaciones entre LinqToSql,
LinqToEnties a LinqToObjects.
ToList
Este operador transforma cualquier secuencia de tipo IEnumerable<T> en List<T>. Es uno de los mñas
utilizados en todo el ecosistema de LinQ,
ya que al realizar esta conversión, la
lista de resultado, tendrá disponible los métodos Add, AddRange, Insert, Remove,
RemoveAt, etc, disponibles con la
interfaz IList<T> e ICollection<T>, que no se
encuentran vacante en la interfaz IEnumerable<T>.
ToList, es de los operadores más utilizados para romper la carga
perezosa o diferida y para ejecutar las consultas de forma inmediata.
Esta es su firma:
IEnumerable<T>
no tiene los métodos (anteriormente nombrados, Add, AddRange, Insert, etc)
disponibles.
ToArray
Mismo comportamiento que para el caso de ToList, pero con una amplitud de uso
mucho más reducida, normalmente utlizada para acciones de compatibilidad.
Firma:
Ejemplo:
Consumimos el operador ToArray,
para reutilizar la variable de tipo string[].
ToDictionary
El operador ToDictionary,
convierte una colección de entrada de tipo IEnumerable<T>,
en un Diccionario Genérico de tipo Clave/Valor.
ToDictionary,
es un poco más complejo que los demás, y posee 4 sobrecargas. Vamos a
destriparlo un poquito y a desvanecer esa dificultad.
Estas son sus 4 sobrecargas:
La primera sobrecarga, aparte del parámetro extensor,
toma un parámetro de tipo Func<TSource,
TKey>, ósea un selector igual que el del operador Select,
con el que valga la redundancia, seleccionaremos el campo u objeto que deseamos
que sea la clave de nuestro Dictionary.
Utilizaremos la siguiente clase para los ejemplos:
Code:
Ejemplo de la primera sobrecarga:
Ejemplo muy sencillo en el que mediante una lambda,
indicamos el campo de nuestra clase MiClase,
que hemos elegido para que sea la clave (Key)
de nuestro diccionario.
La 3ª sobrecarga (la 2ª y la 4ª las dejaremos para el final,
ya que están muy vinculadas), añade un selector más , en este caso Func<TSource, TKey> para la propiedad Value de cada uno de los objetos de
nuestro diccionario.
El ejemplo es similar al anterior, con la disconformidad de
que el valor asignado a la propiedad Value
de cada uno de los elementos de nuestro diccionario, no es una referencia al objeto de la colección
inicial, es un objeto de tipo decimal,
que se corresponde con el tipo de datos de la Propiedad2 de nuestra clase MiClase.
Por este motivo la firma del diccionario que recibirá el resultado del operador
ToDictionary también ha cambiado y
ahora es Dictionary<string,
decimal>.
Para explicar los dos sobrecargas de ToDictionary que nos quedan en el tintero (la 2ª y la 4ª),
vamos a modificar un poco nuestra clase MiClase
y vamos a ejecutar unos de los ejemplos anteriores
Así queda ahora la clase MiClase:
Hemos cambiado valores de propiedades para que concuerden y
entren en conflicto.
Si lanzamos el ejemplo anterior, nos encontraríamos con la
siguiente Excepcion:
Se estaría elevando una Excepción
de tipo System.ArgumentException,
a la hora de ejecutar nuestro operador ToDictionary.
Esto es debido a que la propiedad que hemos seleccionado como Clave (Key) tiene elementos
repetidos, y esto no está permitido dentro de un diccionario.
Para gestionar esta posible colisión, se nos presenta la
posibilidad de añadir otro parámetro más de tipo IEqualityComparer<T>
a cada una de las sobrecargas que ya
hemos visto, y que formarían la 2ª y 4ª sobrecarga. Estos ejemplos tendrían la
misma fórmula que los ya vistos con anterioridad durante el curso. Para ello
ver este link.
ToLookUp
El operador ToLookUp,
es un operador que se podría haber visto perfectamente en la parte dedicada a GrupBy
(Agrupaciones). Este operador es utilizado para facilitar de forma muy
eficiente las creación de secuencias con relaciones de uno a muchos (1 – n). Su uso es muy similar al
operador ToDictionary, con la
salvedad de la multiplicidad de sus datos:
ToDictionary à
Por cada KEY, hay un VALUE relacionado.
ToLookUp à Por cada KEY, hay N VALUES relacionados.
El operador ToLookUp,
trabajará agrupando los elementos según la clave proporcionada.
Para no dejar de lado la comparación con ToDictionary, diremos que ToLookUp, también posee 4
sobrecargas, y que cada una de sus firmas, son muy similares, eso sí, llevadas
a cada uno de sus terrenos.
Para hacer los ejemplos un poco más entendibles, completamos
nuestra clase:
La primera sobrecarga, aparte del parámetro del método
extensor, recibe un selector simple Func<TSource,
TKey> . Con este selector, al igual que en los ejemplos
anteriores, seleccionaremos el campo por el que realizaremos la agrupación.
En el ejemplo, hacemos una agrupación por la propiedad Propiedad1 e imprimimos en la
consola, cada uno de sus valores.
Como con el operador anterior, pasaremos directamente a la
3ª sobrecarga, ya que las restantes (2ª y 4ª), tienen casos muy semejantes.
La tercera sobrecarga, aparte del parámetro extensor y del
selector de la clave, admite un tercer parámetro de tipo selector Func<TSource, TKey>
también para seleccionar el campo(s),
que tendrá el grupo de datos agrupados.
Mismo ejemplo, pero en vez de guardar en el grupo el objeto
de tipo MiClase completo,
guardamos solo el campo Propiedad2.
Para no cambiar demasiado, las sobrecargas 2ª y 4ª, serán
iguales a la 1ª y 3ª, pero añadiendo un parámetro de tipo IEqualityComparer<T>.
Misma explicación y mismo uso que para ToDictionary.
Cast
El operador Cast, es utilizado generalmente para convertir
secuencias no-genéricas (colecciones de datos de tipo object incluídas en el
espacio de nombres System.
Collections), en IEnumerables<T>.
Este operador es un operador muy estricto, y en caso de que alguno de los
elementos de la secuencia no pueda ser convertido, lanzará un InvalidCastException.
Solo tiene una firma:
Ejemplo:
Un ejemplo que elevaría una excepción:
OfType
Tiene las mismas atribuciones que el atributo Cast, con la disconformidad de que
en caso de que haya algún elemento que no se pueda convertir, este se obviará
de la secuencia final de resultado.
Esta es la firma de su método extensor:
Vamos a reutilizar el ejemplo anterior, que elevaba la
excepción, para ver el resultado con el operador OfType:
Cambiando de Cast
a OfType, no generamos excepción alguna, pero perdemos en
el camino el valor “cinco”, del ArrayList,
ya que no puede transformarse al tipo de la secuencia de resultado.
No hay comentarios :
Publicar un comentario