#retosMSDN: Solución al Reto 1 – ¡Ordenando listas!

Aquí tienes la solución que proponemos para el primero de los #retosMSDN: Reto 1 – ¡Ordenando listas!. Pero antes de continuar, queríamos dar las gracias a todos los que habéis participado en el reto, ¡y en especial a todos los que nos habéis enviado vuestras soluciones!

 

Nuestra Solución

Para cumplir el primero de los requisitos, con Visual Studio 2013 podemos crear una librería portable que funcione en aplicaciones hechas con .NET Framework 4.5, y en apps Universales (Windows 8.1+Windows Phone 8.1). Este debería de ser el mínimo de plataformas soportadas al crear la librería para este caso en particular:

 

clip_image002

 

Como ves podríamos haber creado una librería que incluso funcionase en apps para Android e iOS gracias a Xamarin.

 

Para cumplir el segundo de los requisitos, creamos una clase Persona con estas propiedades:

 

 public class Persona
{
    public string Nombre { get; set; }

    public uint Edad { get; set; }
}

Para cumplir el tercer requisito, creamos una clase Reto1 con un método que reciba una lista de personas y que la devuelva ordenada según los criterios especificados: por orden descendente de edad (es decir, los recién nacidos aparecerían al final de la lista), y si dos personas tienen la misma edad, por orden alfabético. En esta ocasión hemos optado por utilizar LINQ (Language-Integrated Query) y expresiones Lambda, que nos permiten ordenar la lista de manera muy sencilla:

 

 public class Reto1
{
    public static List<Persona> OrdenarLista(List<Persona> personas)
    {
        if (personas == null)
        {
            return null;
        }

        return personas.OrderByDescending(p => p.Edad).ThenBy(p => p.Nombre).ToList();
    }
}

 

Ahora, para que este método pase todos los tests y cumplir así el cuarto y último requisito, tenemos que sobrescribir el método Equals de la clase Persona. Si no hacemos esto verás que el test TestOrdenarListaDePersonasConElementos falla en el método CollectionAssert.AreEqual a pesar de estar ordenando bien las listas en nuestro método OrdenarLista. Y esto es así porque el método Equals que tienen los objetos por defecto (y que según la documentación es el que CollectionAssert.AreEqual usa por debajo) determina que dos objetos Persona son iguales sólo si sus referencias son iguales (si apuntan al mismo objeto), y no si los valores de sus propiedades son iguales:

 

 public override bool Equals(Object obj)
{
    Persona otra = obj as Persona;
    return (otra != null) && (this.Edad == otra.Edad) && (this.Nombre == otra.Nombre);
}

 

Y no olvides que si implementas el método Equals, deberías de implementar el método GetHashCode también, como especifica la documentación:

 

 public override int GetHashCode()
{
    return this.Edad.GetHashCode() ^ this.Nombre.GetHashCode();
}

 

El código completo lo puedes encontrar en esta solución de Visual Studio 2013 que puedes descargarte de GitHub.

 

Vuestras Soluciones

Y como casi siempre, no hay una única manera de hacer las cosas. A continuación puedes ver algunas de las otras soluciones que nos habéis propuesto para la implementación de OrdenarLista:

 

@angel_g_santos ha optado por utilizar el método List<T>.Sort:

 

 public static List<Persona> OrdenarLista(List<Persona> lista)
{
    if (null != lista)
    {
        lista.Sort(new Persona.PersonaComparer());
    }

    return lista;
}

 

Donde PersonaComparer lo ha definido así:

 

 
 public class Persona
{
    internal sealed class PersonaComparer : IComparer<Persona>
    {
        public int Compare(Persona x, Persona y)
        {
            int result = y.Edad.CompareTo(x.Edad);
            if (result == 0)
            {
                result = x.Nombre.CompareTo(y.Nombre);
            }

            return result;
        }
    }
}

 

Y @jfmiranda75 también ha optado por LINQ, pero sin usar expresiones Lambda:

 

 public static List<Persona> OrdenarLista(List<Persona> lista) 
{
    if (lista != null)
        return (from p in lista
                orderby p.Edad descending, p.Nombre 
                select p).ToList();
    return null;
}

 

Ya estamos preparando el reto de la semana que viene. El viernes 19 de septiembre ¡volveremos a la carga con los #retosMSDN!

Un saludo,

 

Alejandro Campos Magencio (@alejacma)

Technical Evangelist

PD: Mantente informado de todas las novedades de Microsoft para los desarrolladores españoles a través del Twitter de MSDN, el Facebook de MSDN, el Blog de MSDN y la Newsletter MSDN Flash.