C# - Usando expressões lambda


  O que são Expressões Lambda ?

  As expressões lambdas são funções que podem conter expressões e declarações que são usadas para criar delegates e árvores de expressões onde o tipo das variáveis não precisam ser declarados visto que elas usam métodos anônimos.

As expressões lambda foram incluídas na plataforma .NET para dar suporte a consultas LINQ onde as cláusulas Where são assim compiladas como expressões lambdas.

Elas podem ser consideradas uma forma de delegate que pode passar ou retornar outra função.

Uma expressão lambda é uma função anônima que você pode usar para criar delegados ou tipos de árvore de expressão. Usando expressões lambda, você pode gravar funções locais que podem ser passadas como argumentos ou serem retornadas como o valor de chamadas de função. Expressões lambda são particularmente úteis para escrever expressões de consulta LINQ.http://msdn.microsoft.com/pt-br/library/vstudio/bb397687.aspx

Nota: Delegates permitem que uma classe use métodos de outra classe. Para saber mais sobre delegates leia o meu artigo: Usando Delegates

Assim, as expressões lambdas são funções ou rotinas, sem nome, que calculam e retornam um valor único; elas podem ser usadas em qualquer lugar que um tipo delegate for válido.

Na linguagem C# todas as expressões lambda usam o operador lambda =>, que é lido como "vai para".O lado esquerdo do operador lambda especifica os parâmetros de entrada (se houver) e o direito contém a expressão ou o bloco de instruções A expressão lambda x => x * x é lida assim : " x recebe x vezes x. "

A sintaxe das expressões lambdas

A sintaxe de uma expressão lambda lembra a de uma função padrão. As diferenças são as seguintes:

- Uma expressão lambda não tem um nome.
- Expressões lambda não podem ter modificadores, como Overloads ou Overrides.
- Expressões lambda não usam uma cláusula As para designar o tipo de retorno da função. Em vez disso, o tipo é inferido do valor que o corpo da expressão lambda avalia. Por exemplo, se o corpo da expressão lamba for Where cli.City = "Brazil", seu tipo de retorno é Boolean.
- O corpo da função deve ser uma expressão, não uma instrução. O corpo pode consistir de uma chamada para um procedimento de função, mas não uma chamada para um procedimento sub.
- Nas expressões lambadas não existe uma instrução Return. O valor retornado pela função é o valor da expressão no corpo da função.
- Nas expressões lambdas não existe um instrução End Function.
- Ou todos os parâmetros devem ter tipos de dados especificados ou todos devem ser inferidos.
- Parâmetros opcionais e ParamArray não são permitidos.
- Parâmetros genéricos não são permitidos.

Nota: Com a evolução da plataforma .NET e os novos recursos que foram introduzidos a sintaxe das expressões lambdas foi simplificada, e desta forma você poderá encontrar a mesma função escrita de maneiras diferentes mas o resultado final será o mesmo.

Neste artigo vou ser bem prático e mostrar como podemos usar as expressões lambdas. Cabe a você analisando os exemplos adaptá-los às suas necessidades.

Eu vou procurar na maioria dos exemplos usar a sintaxe VB .NET.

Recursos usados:

Visual Basic 2010 Express Edition (E também o Visual C# 2010 Express Edition)

Usando e Abusando das expressões lambdas

1-) Neste primeiro exemplo temos uma lista de nomes e vamos usar as expressões lambdas para realizar as seguintes operações:

O código na linguagem VB .NET e o resultado são exibidos a seguir:

Module Module1
    Sub Main()
        Dim lista As New List(Of String)()
        lista.Add("Jefferson")
        lista.Add("Jessica")
        lista.Add("Janice")
        lista.Add("Macoratti")
        lista.Add("Mario")
        lista.Add("Mario")
        lista.Add("Janice")
        lista.Add("Miriam")
        'imprimir
        Console.WriteLine("Exibindo a lista Original")
        lista.ForEach(Function(s) ListarNoConsole(s))
        Console.ReadKey()
        ' usar Distinct para eliminar os valores duplicados na lista
        lista = lista.Distinct().ToList()
        Console.WriteLine("Exibindo a lista após Distinct ")
        lista.ForEach(Function(s) ListarNoConsole(s))
        Console.ReadKey()
        ' usar Sort para ordenar a lista
        lista.Sort()
        Console.WriteLine("Exibindo a lista após Distinct e com Sort")
        lista.ForEach(Function(s) ListarNoConsole(s))
        Console.ReadKey()
    End Sub

    Function ListarNoConsole(ByVal nome As String) As String
        Console.WriteLine(nome)
        Return Nothing
    End Function
End Module

Note que foi preciso criar uma função para poder listar os valores usando o método
ForEach que não retorna um valor;

Se você não fazer isso vai obter a mensagem de erro:
Expression does not produce a value

Na versão C# mostrada abaixo funciona sem problemas:

lista.ForEach(s => Console.WriteLine(s));

mas se você usar os conversores a expressão acima será convertida para:

lista.ForEach(Function(s) Console.WriteLine(s))

não vai funcionar pois não retorna um valor.

2-) Agora vamos listar algumas expressões lambdas comparando-as com a abordagem tradicional

Inicialmente vamos declarar alguns números inteiros:

Dim numeros As New List(Of Integer)(New Integer() {1, 9, 7, 4, 5, 6, 3, 8, 2, 10})

A seguir veremos alguns cenários, a utilização das expressões lambdas , a abordagem tradicional e o resultado:

Cenário Usando Expressões lambdas
Ordenação Ascendente For Each item In Numeros.OrderByDescending(Function(i) i)
     Console.WriteLine(item)
Next
Verificar um condição
(verifica os números da
lista são menores que 11)
Dim resultado As Boolean = Numeros.All(Function(i) i < 11)
Verificar um condição
(verifica um número da lista é igual a 5 )
Dim resultado As Boolean = Numeros.Any(Function(i) i = 5)
Obter os 4 números do topo da Lista
Dim subconjunto = Numeros.Take(4)

For Each item In subconjunto
      Console.WriteLine(item)
Next
Fazer a ordenação ascendente, pegar
os números menor que 8 e pegar os 5 números da lista
Dim resultado = _
Numeros.OrderByDescending(Function(i) i).Where(Function(i) i < 8)
.Take(5)

For Each item In resultado
    Console.WriteLine(item)
Next

Localizando itens Dim numero As String = Numeros.Find(Function(p) p = 6)
Usando a abordagem tradicional Resultado
Numeros.Sort(Function(x As Integer, y As Integer) y.CompareTo(x)) 1,2,3,4,5,6,7,8,9,10
Dim resultado As Boolean = True
For Each i As Integer In Numeros
    If i >= 100 Then
         resultado = False
    End If
Next
True
Dim resultado As Boolean = True
For Each i As Integer In Numeros
    If i = 5 Then
         resultado = True
    End If
Next
True
Dim subconjunto = New List(Of Integer)()
For i As Integer = 0 To 4
    If i < Numeros.Count Then
        subconjunto.Add(i)
     End If
Next
1,9,7,4
Numeros.Sort(Function(x As Integer, y As Integer) y.CompareTo(x))

Dim resultado As New List(Of Integer)()
For Each i As Integer In Numeros
  If i < 8 Then
      If resultado.Count < 5 Then
           resultado.Add(i)
       End If
   End If
Next
7,6,5,4,3
For Each i As Integer In Numeros
  If i = 6 Then
           console.Writeline(i)
   End If
Next
6

Com isso fizemos uma revisão de conceitos e mostramos como usar as expressões lambdas e percebemos que a sintaxe das expressões exige menos código.

"Em verdade , em verdade vos digo que vem a hora, e agora é, em que os mortos ouvirão a voz do Filho de Deus, e os que a ouvirem viverão."(João-5:25)

Referências:


José Carlos Macoratti