Listas genéricas: System.Collections.Generic.List<>

Fue conocerlas y no soltarlas!! Las listas genéricas son una de las nuevas clases de .NET 2.0 dentro del namespace System.Collections.Generic.

Como su propio nombre indica, permite listar cualquier cosa, desde un simple listado de strings hasta un listado de la clase más compleja que hayáis creado. Y permite funciones muy útiles para ordenar, buscar un índice, comparar...

A continuación veremos una pequeña introducción al uso de las listas genéricas, para perderle el miedo, animaros a usarlas y para que investiguéis todas sus funcionalidades vosotros mismos.

Vamos a hacer una lista de la típica clase Person:

Person.cs
    public class Person
    {
        private string _nombre;
        /// <summary>
        /// Nombre de la persona
        /// </summary>
        public string Nombre
        {
            get { return _nombre; }
            set { _nombre = value; }
        }

        private string _apellido;
        /// <summary>
        /// Apellido de la persona
        /// </summary>
        public string Apellido
        {
            get { return __apellido; }
            set { __apellido= value; }
        }

        private DateTime _nacimiento;
        /// <summary>
        /// Cuando nació la persona
        /// </summary>
        public DateTime Nacimiento
        {
            get { return _nacimiento; }
            set { _nacimiento = value; }
        }

        public Person(string nombre, string apellido, DateTime nacimiento)
        {
             this.Nombre = nombre;
             this.Apellido = apellido;
             this.Nacimiento = nacimiento;
        }
    }


Listado.cs
        List<Person> personas = new List<Person>();
        personas.Add(new Person("José", "García", new DateTime(1940, 12, 2)));
        personas.Add(new Person("Pedro", "López", new DateTime(1992, 2, 22)));
        personas.Add(new Person("Antonio", "Pérez", new DateTime(1976, 6, 21)));


La lista es una especie de array que se va redimensionando conforme a las necesidades. Al crear la variable List<> se inicializa su capacity, que se aumenta conforme la lista va creciendo. Pero, a no ser que indiquemos lo contrario, es totalmente transparente a nosotros.

La cuestión es que nosotros podemos hascer la lista tan grande como queramos, y listarlo fácilmente. Por ejemplo, vamos a ver dos modos de mostrar los elementos de la lista, colocando el resultado en un StringBuilder:

Listado.cs
    private void Mostrar1(List<Person> personas)
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        foreach (Person persona in personas)
        {
            sb.AppendLine(persona.Nombre + " " + persona.Apellido + "<br />");
        }
    }

Listado.cs
    private void Mostrar2(List<Person> personas)
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        for (int i = 0; i < personas.Count; i++)
        {
            sb.AppendLine(personas[i].Nombre + " " + personas[i].Apellido + "<br />");
        }
    }

A mí personalmente me gusta más el modo 1

Pero obviamente, no es mostrar lo único que se puede hacer con una lista genérica. Por ejemplo podemos buscar los elementos de la lista que cumplan las condiciones que le indiquemos. Por ejemplo, queremos encontrar las personas que hayan nacido a partir de 1975 (a las que llamaremos jóvenes ):

Listado.cs
    private List<Person> Jovenes(List<Person> personas)
    {
       // Encuentra todas las personas que "jóvenes"
        return personas.FindAll(encuentra);

       // Encuentra la primera persona joven de la lista
       // personas.Find(encuentra);

       // Encuentra el índice de la primera persona joven de la lista
       //  personas.FindIndex(encuentra);

       // Encuentra la última persona joven de la lista
       // personas.FindLast(encuentra);

       // Encuentra el índice de la última persona joven de la lista
       //  personas.FindLastIndex(encuentra);

    }

    private bool encuentra(Person P)
    {
        return P.Nacimiento.Year > 1975;
    }


Y del mismo modo podemos realizar varias operaciones interesantes, como insertar en cierto índice (insert), borrar una entrada (remove), vaciar la lista (clear), ordenarla (sort), comprobar si existe cierte entrada (exist)...

Listado.cs
    private void Varios(List<Person> personas)
    {
       // Inserta una nueva persona en el índice 2 (tercera posición)
        personas.Insert(2, new Person("Javier", "Navarro", new DateTime(1981, 12, 21)));

       // Ordena el listado de personas según su edad
        personas.Sort(ordenarPorEdad);

       // Devuelve si existen jóvenes en el listado. En este caso devolvería true
       bool existenJovenes = personas.Exists(encuentra);

       // Borrar la Persona que está en la tercera posición (índice 2)
        personas.RemoveAt(2);

       // Borra todas las personas jóvenes
        personas.RemoveAll(encuentra);

       // Ahora devolvería false
       bool existenJovenes = personas.Exists(encuentra);


       // Vacía la lista
        personas.Clear();
    }

    private bool encuentra(Person P)
    {
        return P.Nacimiento.Year > 1975;
    }

    private int ordenarPorEdad(Person P1, Person P2)
    {
        return P1.Nacimiento.CompareTo(P2.Nacimiento);
    }

Como véis, es muy sencillo trabajar con listas genéricas, y realmente resultan muy útiles en muchos campos.

Por ejemplo, se puede marcar como datasource de cualquier ServerControl de datos, por ejemplo:

Listado.cs
    private void arreglaDatos(List<Person> personas)
    {
       GridView1.DataSource = personas;
       GridView1.DataBind();
    }


Personalmente, los datos que me devuelve mi capa DAL están ya en una lista genérica que almacena elementos de la clase que me he creado, y después ya los trato como interese en el resto de capas BLL y capa de presentación.