As Lambda Expressions são funções anónimas que podem conter expressões e declarações, e que podem ser usadas para criar expressões ou Delegates. As Lambda Expressions são uma novidade do Visual Studio 2008, e utilizam métodos anónimos (Anonymous Methods), não sendo por isso necessário declarar o tipo de variáveis usadas. As Lambda Expressions conseguem detectar o tipo de dados usados, sendo por isso necessário definir Option Infer On (está por defeito desta forma).
Um exemplo simples de uma expressão Lambda:
Dim lambda1 As Func(Of Integer, Integer) = Function(x) x * x
Debug.WriteLine(lambda1(2).ToString())
Neste pequena expressão, e criado uma Func Delegate, que irá receber um valor do tipo Integer e devolver como resultado do tipo Integer. Irá depois multiplicar o valor recebido e, neste exemplo, o resultado será 4.
Um exemplo um pouco mais complexo, mas também bastante simples de entender:
Dim lambda2 As Func(Of Integer, String) = _
Function(x) If(x <= 10, 10, x * x).ToString()
Debug.WriteLine(lambda2(15))
Neste caso, irá ser indicado um Integer e devolvido uma String, sendo efectuada uma verificação. Caso o valor indicado seja menor ou igual a 10, irá devolver 10, caso contrário, irá devolver o dobro do valor indicado. Neste caso o resultado será 255.
Isto é semelhante a criar uma função externa, que faça esta validação, mas apenas numa linha de código.
Mas existem mais aplicações para as expressões Lambda. Por exemplo para atribuir Delegates a um objecto:
Dim btn As New Button() With {.Text = "Go ...", .Name = "New Button"}
Me.Controls.Add(btn)
AddHandler btn.Click, Function(s, ev) _
MessageBox.Show(DirectCast(s, Button).Name)
Este exemplo adiciona um botão ao Form e irá mostrar o nome do botão quando este for clicado. O “s” é o Sender e o “ev” o EventArgs. No entanto, apenas na versão 2010, é possível criar funções mais complexas, com mais linhas, sendo que o C# 3.0 já o permite.
Mas mais alguns exemplos de como as expressões Lambda podem ajudar em simplificar o código. Considerando esta simples classe para demonstração:
' O atributo DebuggerStepThrough() irá fazer que o compilador
' não pare enquanto se está a fazer o debug no código do programa
<Diagnostics.DebuggerStepThrough()> _
Public Class student
Private m_Name As String
Public Property Name() As String
Get
Return m_Name
End Get
Set(ByVal value As String)
m_Name = value
End Set
End Property
Private m_Age As Int16
Public Property Age() As Int16
Get
Return m_Age
End Get
Set(ByVal value As Int16)
m_Age = value
End Set
End Property
End Class
A esta simples classe, apenas com duas propriedades – Name, Age – iremos criar uma lista, do tipo student, e adicionar alguns registos.
' Cria uma nova lista de estudantes (Classe student)
Dim studentList As New List(Of student)
' Adiciona vários registos com idades aleatórias entre os 6 ao 50 anos
Dim rnd As New Random
For x As Short = 0 To 999
Dim newStudent As New student() With { _
.Name = "Student "& x.ToString, _
.Age = CShort(rnd.Next(6, 50))}
studentList.Add(newStudent)
Next
Ok, com a classe criada e com uma lista do tipo student vamos filtrar informação!Vamos procurar todos os teenagers na lista (dos 13 aos 19).
Alguns exemplos de como podemos filtrar os dados:
Usando Delegates
Criamos uma função no programa, que retorna um resultado booleano:
Function GetTeenagers(ByVal s As student) As Boolean
Return s.Age >= 13 And s.Age <= 19
End Function
E depois:
Dim delResult As List(Of student) = _
studentList.FindAll(New Predicate(Of student)(AddressOf GetTeenagers))
For Each s As student In delResult
Debug.WriteLine(String.Format("Name: {0}, Age: {1}", s.Name, s.Age))
Next
Usando LINQ to Objects
Dim linqResult = From s As student In studentList _
Let st As student = DirectCast(s, student) _
Where st.Age >= 13 And st.Age <= 19 _
Select st
For Each s As student In linqResult
Debug.WriteLine(String.Format("Name: {0}, Age: {1}", s.Name, s.Age))
Next
Usando Lambda Expressions
Dim lambdaResult As List(Of student) = _
studentList.Where(Function(s) s.Age >= 13 And s.Age <= 19).ToList()
For Each s As student In lambdaResult
Debug.WriteLine(String.Format("Name: {0}, Age: {1}", s.Name, s.Age))
Next
Simples e prático!
Além disso podemos ainda, de uma forma bastante simples, fazer algumas operações, como calcular a média de idades ou somar todas as idades:
' Calcula a médias de idades
Dim average = studentList.Average(Function(s) s.Age)
Debug.WriteLine(average.ToString)' Soma todas as idades
Dim sum = studentList.Sum(Function(s) s.Age)
Debug.WriteLine(sum.ToString)
Ou procurar um registo na studentList:
Dim found = studentList.Find(Function(s) s.Name = "Student 5")
If found IsNot Nothing Then
Debug.WriteLine(found.Age.ToString())
End If
Como podem ver, as Lambda Expressions podem simplificar algumas operações no código e versão 2010 do Visual Studio irá potenciar ainda mais a sua utilização.
Estas são algumas das aplicações, mas existem mais, que oportunamente poderei mostrar.
3 comentários:
Excelente artigo! Não fazia a mínima ideia que o VB.net suportava as funções lambda.
Sem dúvida que vou começar a usá-las para pequenos filtros entre outras funções mais simples sem muito esforço ;)
Muito interessante!
Não sabia que existia.. é um conceito parecido com Lua scripts..
Thank you!
Funciona apenas com .NET 3.5..
Por enquanto meus projectos ficam todos com o .NET 2.0, porque quase toda a gente tem instalado..
É um questão de tempo :)
Enviar um comentário