Friday, August 15, 2008 1:15 PM

 

Mudando o target do projeto de .Net framework 2.0 para 3.5 (veja multi-targeting support), já existe um ganho imediato: O namespace System já oferece o delegate System.Predicate<T>, portanto posso apagar o meu delegate e recompilar o código. Isto mostra a aproximação do C#, e do .Net framework, dos paradigmas da programação funcional.

Mas existem outras novidades que podemos utilizar.

Extension methods

Com ele podemos estender um tipo sem precisar alterar, ou herdar, este tipo. Bem interessante, apesar de não ajudar muito na legibilidade do seu código. Mas em alguns casos, pode ajudar bastante.

Por exemplo, uma funcionalidade de Filtro, como a nossa, pode ser utilizada por qualquer coleção que implementa IEnumerable. Por isto, podemos criar um Extension method para este tipo.

 Figura3

 

 

 

 

 

 

 

A lógica em si não muda nada, mas alguns detalhes o tornam um extension method. A primeira é a classe tem que ser estática. O método também precisa ser estático. A Figura mostra isto. O terceiro ponto é o modifier this no parâmetro collection. Ele indica que um objeto do tipo IEnumerable poderá chamar este método, como se ele pertencesse ao tipo. Veja como muda a sua utilização:

Chamada antiga:

private List<Cliente> GetClientesDoPara(List<Cliente> clientes)
{
    return (List<Cliente>) Filter(clientes, ClienteResideNoPara);
}

Nova chamada:

private List<Cliente> GetClientesDoPara(List<Cliente> clientes)
{
    return (List<Cliente>) clientes.Filter(ClienteResideNoPara);
}

Ao invés de enviar a coleção de clientes como parâmetro da função, o Filter torna uma função daquele tipo. Só para ilustrar, veja que posso utilizar este método em qualquer IEnumerable como, por exemplo, uma coleção de serviços instalados na máquin, do System.ServiceProcess

public void FilterServicesTest()
{
    List<ServiceController> servicos = (List<ServiceController>) ServiceController.GetServices()
                                                                                    .Filter(ServicosIniciados);
}

private bool ServicosIniciados(ServiceController controller)
{
    return controller.Status == ServiceControllerStatus.Running;
}

Lambda expressions

Em poucas palavras, as expressões lambda permitem definir uma função anônima, sem a necessidade de formalizar um método. Você pode ler um pouco mais aqui ou buscar na internet. A sintaxe de uma expressão bem simples é:

    x => x * x

No lado esquerdo do operador “=>” definem-se os parâmetros da função, neste caso o x, do lado direito, a função que mutiplica o x por ele mesmo, ou seja, sua raiz quadrada.

É possível utilizar expressões lambdas para simplificar a chamada do Filter. Até agora estávamos usando:

private bool ClienteResideNoPara(Cliente cliente)
{
    return cliente.Estado.Equals("Pará");
}

private List<Cliente> GetClientesDoPara(List<Cliente> clientes)
{
    return (List<Cliente>) clientes.Filter(ClienteResideNoPara);
}

Ao invés de definir uma função que implementa o delegate, posso simplesmente passar uma lambda como parâmetro e dispensar o método ClienteResideNoPara:

private List<Cliente> GetClientesDoPara(List<Cliente> clientes)
{
    return (List<Cliente>) clientes.Filter(x => x.Estado.Equals("Pará"));
}

O charme da sintaxe Linq

A sintaxe do Linq definitivamente é garbosa, dá um tom moderno ao código-fonte. Mas não é só isto. Um query Linq também pode nos poupar de utilizar alguns statements, como o foreach e o if.

public static IEnumerable<T> Filter<T>(this IEnumerable<T> collection, 
                                                                 Predicate<T> filter)
{
    var result = from item in collection
                 where filter(item)
                 select item;

     return result.ToList<T>();
}

Elegante, simples e expressivo.

A seguir vamos falar um pouco mais Linq.

< Exemplos >

Comments

No comments posted yet.
Post Comment
Title *
Name *
Email (never displayed)
Website
Comment * (Allowed tags: blockquote, a, strong, em, p, u, strike, super, sub, code)  
Please add 4 and 4 and type the answer here: