Tabla de contenidos:
AsEnumerable
El operador AsEnumerable convierte una secuencia en una enumeración del tipo IEnumerable
Código necesario para los ejemplos:
Un objeto del tipo IQueryable como resultado de un LINQ to SQL:
IQueryable<Persona> personas = db.Persona;
NOTA: db es una instancia de un System.Data.Linq.DataContext o en otras palabras, una instancia del LINQ To SQL. Es un ejemplo imaginario para simplificar el ejemplo.
Volver al operador AsEnumerable
AsEnumerable:
public static IEnumerable<TSource> AsEnumerable<TSource>( this IEnumerable<TSource> source )
͉ste operador puede parecer extraño, absurdo. Un operador que quiere transformar una secuencia a un IEnumerable
Los operadores estándar son los de LINQ To Objects y esos son miembros de IEnumerable
LINQ to SQL trabaja con IQueryable y éste implementa sus propios operadores.
Teniendo esto en consideración, IQueryable puede tener operadores como… Where, Select, etc. La cosa es que están implementados de otra forma puesto que trabajan con otros tipos de datos. No solo eso, puede que no implemente ciertos operadores que nosotros necesitamos usar.
¿Qué podemos hacer?
Si, lo que estás pensando. Podemos convertir nuestra secuencia IQueryable
¿Cómo? Así:
IEnumerable<Persona> ienupersonas = personas.AsEnumerable();
Con esto hemos convertido de IQueryable
Hemos podido usar ese método en el IQueryable
Volver a la tabla de contenidos
AsQueryable
El operador AsQueryable convierte una enumeración del tipo IEnumerable en una del tipo IQueryable
Código necesario para los ejemplos:
Una tabla de nuestra base de datos convertida a IEnumerable
IQueryable<Persona> personas = db.Persona; IEnumerable<Persona> ienupersonas = personas.AsEnumerable();
Volver al operador AsQueryable
AsQueryable:
public static IQueryable<TElement> AsQueryable<TElement>( this IEnumerable<TElement> source )
͉ste método es justo lo contrario de AsEnumerable. Recomendaría leer su descripción para mejor compensión.
Básicamente, si tienes un objeto del tipo IEnumerable como por ejemplo el de nuestro código adjunto, puedes necesitar convertirlo a IQueryable.
Por ejemplo, tenemos un IQueryable proveniente de una tabla de nuestra base de datos. La convertimos a IEnumerable como ya se explicó. Hacemos el trabajo que tengamos que hacer y luego la volvemos a convertir a IQueryable.
Para hacer esto último, hacemos un:
IQueryable<Persona> iquerypersonas = ienupersonas.AsQueryable();
Podríamos haber reusado el objeto personas pero era para dar otro ejemplo.
Volver a la tabla de contenidos
Cast
El operador Cast puede convertir un array estandar a un objeto que implementa IEnumerable
Código necesario para los ejemplos:
Un array de enteros:
int[] arrayNum = {1, 2, 3, 4, 5};
Cast:
public static IEnumerable<TResult> Cast<TResult>( this IEnumerable source )
El operador Cast se usa con la secuencia que queremos convertir a un tio. Devolverá dicha secuencia convertida a una enumeración de dicho tipo.
Por ejemplo, queremos convertir nuestro array de enteros a una enumeración de enteros:
IEnumerable<int> enuNum = arrayNum.Cast<int>();
El resultado es:
1
2
3
4
5
Ahora la pregunta es: ¿Para qué queremos convertir el array a un IEnumerable
Un array normal y corriente no implementa IEnumerable
IEnumerable<int> enuNum = arrayNum.Cast<int>().Select(i => i*i);
Ahora gracias a Cast hemos podido aplicarle un Select.
El resultado de esto último sería:
1
4
9
16
25
Volver a la tabla de contenidos
ToArray
El operador ToArray convierte una enumeración del tipo IEnumerable
Código necesario para los ejemplos:
Una clase persona:
public class Persona
{
public string Nombre { get; set;}
public int Edad { get; set;}
public string Ciudad { get; set; }
public Persona(string nombre, int edad, string ciudad)
{
Nombre = nombre;
Edad = edad;
Ciudad = ciudad;
}
}
Una lista de personas:
List<Persona> personas = new List<Persona>
{
new Persona("Rodriguez, Jesús", 24, "Cádiz"),
new Persona("Bautista, Jesús", 15, "Alicante"),
new Persona("Perez, Juan", 15, "Cádiz"),
new Persona("García, Javier", 24, "Málaga"),
new Persona("Toledo, María", 37, "Málaga")
};
ToArray:
public static TSource[] ToArray<TSource>( this IEnumerable<TSource> source )
͉ste operador toma como parámetro un objeto IEnumerable
Por ejemplo, tenemos una listra de personas, queremos crear un array con todos los nombres de las personas.
Lo haré en dos pasos para verlo mejor
IEnumerable<string> nombres = personas.Select(p => p.Nombre); string[] arrayNombres = nombres.ToArray();
Como ves, proyecto solo los nombres en una enumeración de string y luego convierto dicha enumeración en un array de string.
Se puede reducir a un paso también:
string[] nombres = personas.Select(p => p.Nombre).ToArray();
En ambos casos, se imprimirían los nombres:
Rodriguez, Jesús
Bautista, Jesús
Perez, Juan
García, Javier
Toledo, María
Volver a la tabla de contenidos
ToDictionary
El operador ToDictionary convierte una enumeración del tipo IEnumerable en un Dictionary
- Código necesario para los ejemplos
- ToDictionary estándar
- ToDictionary + comparador personalizado
- ToDictionary + proyector elemento
- ToDictionary + proyector elemento + comparador personalizado
Código necesario para los ejemplos:
Una clase persona:
public class Persona
{
public string Nombre { get; set;}
public string Edad { get; set;}
public string Ciudad { get; set; }
public Persona(string nombre, string edad, string ciudad)
{
Nombre = nombre;
Edad = edad;
Ciudad = ciudad;
}
}
Una lista de personas:
List<Persona> personas = new List<Persona>
{
new Persona("Rodriguez, Jesús", "24", "Cádiz"),
new Persona("Bautista, Jesús", "15", "Alicante"),
new Persona("Perez, Juan", "16", "Cádiz"),
new Persona("García, Javier", "26", "Málaga"),
new Persona("Toledo, María", "37", "Málaga")
};
Un comparador personalizado:
public class StringANumero : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return (Int32.Parse(x) == Int32.Parse(y));
}
public int GetHashCode(string obj)
{
return Int32.Parse(obj).ToString().GetHashCode();
}
}
Volver al operador ToDictionary
ToDictionary estándar:
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector )
ToDictionary recibe un delegado que usaremos para seleccionar la clave. Devuelve un diccionario cuyas claves son las que hemos seleccionado e irán con su valor correspondido. A diferencia de ToLookup en un diccionario las claves van asociadas a un solo valor. Las claves no se pueden repetir.
Por ejemplo, queremos transformar nuestra lista de personas a un diccionario donde la clave sea el nombre:
Dictionary<string, Persona> dictNombres = personas.ToDictionary(p => p.Nombre);
Y tal como pasa con ILookup podemos hacer un:
Persona jesus = dictNombres["Rodriguez, Jesús"];
Volver al operador ToDictionary
ToDictionary + comparador personalizado:
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer )
Con esta sobrecarga podemos crear un diccionario a partir de una clave, pero ahora usaremos un comparador personalizado para comparar las claves.
Vamos a verlo:
Dictionary<string, Persona> dictEdad = personas.ToDictionary(p => p.Edad, new StringANumero());
Nada nuevo, usamos nuestro comparador. Ahora bien, quiero recoger del diccionario la persona de 24 años, o sea, Jesús:
Persona jesus = dictEdad["000024"];
Ea, ahi está… ¿Pero por qué funciona?
Como ya vimos en ToLookup, cuando le pedimos al diccionario que nos devuelva el valor asociado a una clave (en este caso “000024″) lo que hace es buscar dicha clave en el diccionario comparando la clave que le pasamos con cada clave del diccionario. Al usar un comparador personalizado, esas comparaciones se hacen a través de nuestro comparador personalizado. Entonces, el método Parse del de la clase Int32 lo que hace es convertir nuestra cadena “000024″ a un Int32 para ello quita los ceros de la izquierda y quedaría simplemente como 24, claro, cuando llega a la entrada de Jesús ve que su edad es 24 también y la da por válida.
Volver al operador ToDictionary
ToDictionary + proyector elemento:
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector )
Ahora podemos definir cual será la clave y como serán los elementos gracias al delegado que nos permite proyectar lo que necesitemos de cada elemento.
Vamos a crear un diccionario con el nombre como clave, pero solo nos vamos a quedar con la ciudad, nada más:
Dictionary<string, string> dictNombre = personas.ToDictionary(p => p.Nombre, p => p.Ciudad);
Si imprimieramos el diccionario, conseguiríamos algo así:
[Rodriguez, Jesús, Cádiz]
[Bautista, Jesús, Alicante]
[Perez, Juan, Cádiz]
[García, Javier, Málaga]
[Toledo, María, Málaga]
Volver al operador ToDictionary
ToDictionary + proyector elemento + comparador personalizado:
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer )
Además de la clave y el proyector para los elementos, podemos usar un comparador personalizado para comparar las claves.
Vamos a mejorar el ejemplo anterior creando un diccionario con la edad como clave pero solo necesitamos el nombre de la persona y nada más:
Dictionary<string, string> dictEdad = personas.ToDictionary(p => p.Edad, p => p.Nombre, new StringANumero());
Ahora por cada clave (edad) solo habrá una cadena con el nombre y no todo el objeto Persona entero. Y cada vez que le pedimos al diccionario que nos devuelva un nombre, comprobará cada edad con nuestro comparador personalizado.
Volver a la tabla de contenidos
ToList
El operador ToList convierte una enumeración del tipo IEnumerable
Código necesario para los ejemplos:
Una clase persona:
public class Persona
{
public string Nombre { get; set;}
public int Edad { get; set;}
public string Ciudad { get; set; }
public Persona(string nombre, int edad, string ciudad)
{
Nombre = nombre;
Edad = edad;
Ciudad = ciudad;
}
}
Una lista de personas:
List<Persona> personas = new List<Persona>
{
new Persona("Rodriguez, Jesús", 24, "Cádiz"),
new Persona("Bautista, Jesús", 15, "Alicante"),
new Persona("Perez, Juan", 15, "Cádiz"),
new Persona("García, Javier", 24, "Málaga"),
new Persona("Toledo, María", 37, "Málaga")
};
ToList:
public static List<TSource> ToList<TSource>( this IEnumerable<TSource> source )
Recibe como parámetro el objeto tipo IEnumerable
Por ejemplo, creamos una enumeración proyectando solo los nombres de las personas, luego lo ordenamos y por último lo convertimos a una lista:
IEnumerable<string> orderYSelect = personas.OrderBy(p => p.Nombre).Select(p => p.Nombre); List<string> nombresOrdenados = orderYSelect.ToList();
O lo que es lo mismo:
List<string> nombresOrdenados = personas.OrderBy(p => p.Nombre).Select(p => p.Nombre).ToList();
El resultado de imprimir esto sería:
Bautista, Jesús
García, Javier
Perez, Juan
Rodriguez, Jesús
Toledo, María
Volver a la tabla de contenidos
Consideraciones finales
Algo importante que añadir:
Como ya dije, la gran mayoría de operadores de LINQ son de ejecución diferida, esto quiere decir que cuando lo aplicas a un objeto y obtienes un IEnumerable
Visto de otra forma, si tienes un:
IEnumerable<string> nombres = personas.Select(p => p.Nombre);
Realmente IEnumerable
Ahora bien, los operadores del tipo ToXXX hacen que se ejecute directamente dichas instrucciones y cree una colección con todos los elementos procesados.
Eso quiere decir que si haces un:
List<string> nombres = personas.Select(p => p.Nombre).ToList();
Estarás haciendo que se procese cada persona para proyectarle el nombre y meterlo en una lista.
En resumen, los métodos ToXXX son mucho más lentos que los de ejecución diferida, así que hay que intentar usar estos últimos primero puesto que así ganaremos mucho en rendimiento.
Volver a la tabla de contenidos
Tags: LINQ


Hola
No entiendo esto “Cuando iteras sobre ese objeto es cuando realmente..”
Que significa iters? Es cuando le asigno la variable a una grilla:
DataGridView.DataSource = xListaClientes;
Eso es iterar?
Graciasss
Hola, iterar es ir elemento a elemento, iterar sobre una lista por ejemplo sería ir elemento por elemento haciendo algo.
Tengo una pregunta:
Estoy desarrollando en Visual Studio 2010 para Windows Phone 7 y cuando quiero converetir un IQueryable a un List me sale un error que dice InvalidCastException. Es decir, no puedo convertir y no entiendo por qué!
Agradecería tu ayuda.
Tendría que ver algo de código para probarlo yo al menos
(un pastebin o algo)