C# Tips & Tricks – Ordenação com LINQ To Objects

É comum a necessidade de realizarmos a ordenação de arrays, listas genéricas e dicionários. Apesar de ser um assunto antigo e já conhecido pela maioria dos desenvolvedores, vamos mostrar aqui como fazer a ordenação de uma maneira simples usando o LINQ To Objects.

Vamos demonstrar esse método de ordenação contrastando a maneira anterior à introdução do LINQ no Framework (antes da versão 3.0) e após o LINQ.

Vamos criar uma classe simples para utilizarmos posteriormente em nosso código.

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }

    public override string ToString()
    {
        return string.Format("{0} {1}\nEmail: {2}", FirstName, LastName, EmailAddress);
    }
}

Essa classe representa um cliente que possui um nome, sobrenome e e-mail. Além disso, sobrescreve o método ToString de System.Object e utiliza propriedades automáticas (C# 3.0).

Vamos agora criar uma lista genérica de clientes.

var lista = new List<Customer>
{
    new Customer { FirstName = "Ari", LastName = "Raimundo", EmailAddress = "ari@mail.com"},
    new Customer { FirstName = "Anders", LastName = "Hejlsberg", EmailAddress = "anders@mail.com"},
    new Customer { FirstName = "Bill", LastName = "Gates", EmailAddress = "bill@mail.com"},
    new Customer { FirstName = "Jesse", LastName = "Liberty", EmailAddress = "jesse@mail.com"}
};

Esse post irá demonstrar como poderíamos ordenar essa lista de clientes pela propriedade FirstName (primeiro nome).

Antes da introdução do LINQ a ordenação era realizada com o método Sort da lista (ou Array.Sort em caso de arrays) que era sobrecarregado. Uma das assinaturas desse método solicitada uma classe que herdava de IComparer<T> e uma outra um delegate Comparison<T>.  Existem outras maneiras mas vou simplificar e demonstrar somente essas duas.

Vamos então criar uma classe que herda de IComparer<T> e que realiza a ordenação pela propriedade FirstName.

public class CustomerComparer : IComparer<Customer>
{
    public int Compare(Customer x, Customer y)
    {
        return x.FirstName.CompareTo(y.FirstName);
    }
}

Para ordenarmos a lista faríamos então:

lista.Sort(new CustomerComparer());

Vamos agora apresentar a maneira de ordenar usando o delegate Comparison<T>. Para isso, é necessário a criação do método abaixo:

static int CompareCustomerByFirstName(Customer x, Customer y)
{
    return x.FirstName.CompareTo(y.FirstName);
}

Para ordenar a lista faríamos então:

lista.Sort(CompareCustomerByFirstName);

O delegate Comparison<T> poderia ser passado para o método usando anonymous delegates também, que já estava presente na versão 2.0. Para ordenar a lista ficaria assim:

lista.Sort(delegate(Customer x, Customer y)
{
    return x.FirstName.CompareTo(y.FirstName);
});

Mas agora vamos utilizar o LINQ to Objects para ordenar a nossa lista, ou melhor, vamos realizar uma consulta em nossa lista e retornar uma nova lista ordenada.

var l = (from c in lista
         orderby c.FirstName
         select c).ToList();

Para simplificar ainda mais vamos utilizar extension methods (method-based queries).

var l = lista.OrderBy(c => c.FirstName).ToList();

Vejam que se tivéssemos a necessidade de ordenar a lista usando 2 propriedades, por exemplo: FirstName de maneira ascendente e LastName de maneira descendente, seria um pouco complexo usando IComparer<T> ou Comparable<T>. Veja abaixo o código em LINQ para fazermos isso.

var l = (from c in lista
         orderby c.FirstName, c.LastName descending 
         select c).ToList();

Ah, se quisermos mostrar o conteúdo da lista na tela podemos usar o código abaixo.

l.ForEach(c => { Console.WriteLine(c.ToString()); });

Os métodos de ordenação acima demonstrados podem ser utilizados para qualquer tipo que implementa IEnumerable ou IEnumerable<T> (arrays, listas genéricas e dicionários).

É fato que o LINQ simplifica muito a nossa vida!

Alguns links de ajuda:

LINQ To Objects
http://bit.ly/8OHCr3

List<T>.Sort Method
http://bit.ly/71Fd9B

Um comentário:

  1. Opa gostei do seu blog, vi que é de curitiba, me manda seu e-mail para conversarmos marcio@marcioalthmann.net

    Abraços.

    ResponderExcluir