VB .NET - Usando operadores LINQ


 Hoje vou mostrar como usar alguns operadores LINQ usando a linguagem VB .NET.

A LINQ é que ela foi criada com o objetivo de simplificar consultas a informações na memória em coleções como listas e arrays, bem como informações armazenadas em base de dados , documentos XML , arquivos e outras fontes de dados. Ela realiza uma mapeamento objeto Relacional de forma que a o acesso a dados é feito através do framework LINQ e as instruções SQL são geradas implicitamente.

Neste artigo eu mostrar como usar os operadores  ThenBy, Any, Concat, Cast, Distinct, ElementAt, Repeat, Last e Except.

Esses são apenas alguns dos muitos operadores que a LINQ tem em seu arsenal. Veja abaixo uma relação dos operadores:

Operador Lazy ? Descrição
Aggregate No Aplica uma função a uma seqüência , originando um valor único
All No Aplica uma função a uma seqüência para verificar se todos os elementos satisfazem a função.
Any No Aplica uma função a uma seqüência para verificar se qualquer elemento satisfaz a função.
Average No Calcula a média de um seqüência numérica.
Concat Yes Produz a concatenação de duas seqüências S1 e S2.
Contains No Procura a seqüência para verificar se a mesma contem um dado elemento.
Count No Conta o numero de elementos em uma seqüência , originando um resultado inteiro.
DefaultIfEmpty Yes Data uma seqüência S, produz S ou a seqüência com o valor padrão se S estiver vazia.
Distinct Yes Retorna a seqüência com valores duplicados eliminados.
ElementAt No Retorna o i-ésimo elemento de uma seqüência.
ElementAtOrDefault No Retorna o i-ésimo elemento de uma seqüência se a seqüência ou o padrão se a seqüência estiver vazia.
Empty Yes Produz uma seqüência vazia.
EqualAll No Compara duas seqüências por igualdade.
Except Yes Dada duas seqüências S1 e S2, retorna o conjunto diferença S1 S2.
First No Retorna o primeiro elemento da seqüência.
FirstOrDefault No Retorna o primeiro elemento da seqüência, ou o valor padrão se a seqüência esta vazia.
GroupBy Yes Agrupa os elementos de uma seqüência pela chave.
GroupJoin Yes Realiza uma junção de duas seqüências S1 e S2 produzindo um resultado hierárquico.
Intersect Yes Dada duas seqüências S1 e S2, retorna o conjunto intersecção de S1 e S2
Join Yes Realiza uma junção tradicional interna de duas seqüências S1 e S2.
Last No Retorna o último elemento de uma seqüência.
LastOrDefault No Retorna o último elemento de uma seqüência ou o valor padrão se a seqüência estiver vazia.
LongCount No Conta o número de elementos em uma seqüência, produzindo um resultado do tipo long.
Max No Retorna o valor máximo de uma seqüência.
Min No Retorna o valor mínimo de uma seqüência
OfType Yes Produz os elementos de uma seqüência que coincide com um dado tipo.
OrderBy Yes Ordena uma seqüência de elementos pela chave na ordem ascendente.
OrderByDescending Yes Ordena uma seqüência de elementos pela chave na ordem descendente.
Range Yes Produz uma seqüência de inteiros em um dado intervalo.
Repeat Yes Produz uma seqüência de valores pela repetição de um dado valor n vezes.
Reverse Yes Inverte os elementos de um seqüência.
Select Yes Aplica a função de projeção a uma seqüência , originando uma nova seqüência.
Single No Retorna o único elemento de um seqüência única.
SingleOrDefault No Retorna o único elemento de uma seqüência , ou valor padrão se estiver vazia.
Skip Yes Pula o primeiro elemento de uma seqüência , produzindo os elementos restantes.
SkipWhile Yes Data uma função F e seqüência S, pula os elementos iniciais de S onde F é verdadeira.
Sum No Calcula a soma de uma seqüência numérica.
Take Yes Produz os primeiros n elementos de uma seqüência.
TakeWhile Yes Dada uma função F e uma seqüência S, produz os elementos iniciais de S onde F for verdadeira.
ThenBy Yes Toma uma seqüência ordenada e produz uma secundária , na ordem ascendente.
TheyByDescending Yes Toma uma seqüência ordenada e produz uma secundária , na ordem descendente.
ToArray No Percorre uma seqüência, capturando os resultados em um array.
ToDictionary No Percorre uma seqüência, capturando os resultados em um Dictionary<K, V>.
ToList No Percorre uma seqüência, capturando os resultados em uma List<T>.
ToLookup No Percorre uma seqüência, capturando os resultados em um Lookup<K, IEnumerable<V>>.
ToSequence Yes Converte uma seqüência em uma seqüência IEnumerable para usar com consulta padrão.
Union Yes Dada duas seqüências S1 e S2 retorna o conjunto união de S1 e S2.
Where Yes Aplica uma função Booleana a uma seqüência, produzindo uma sub seqüência.

Obs: Lazy é um atributo que significa 'quanto mais tarde melhor' e tem o objetivo de carregar um item sob demanda. (Lazy Loading)

Recursos usados :

Criando o projeto no Visual Studio

Abra o Visual Studio 2013 Express Edition for windows desktop e clique em New Project;

Selecione a linguagem Visual Basic e o template Windows Forms Application;

Informe o nome VBNET_LINQ_Operadores ou outro nome de sua preferência e clique OK.

A seguir inclua a partir da ToolBox os seguintes controles no formulário form1.vb:

Disponha os controles no formulário conforme a figura abaixo:

Vamos criar 3 arrays, dois arrays de string e um array de inteiros para isso vamos declarar as variáveis abaixo no início do formulário:

Dim numerosString() As String
Dim numeros() As Integer
Dim nomes() As String

Agora para criar os arrays vamos definir o código abaixo no evento Click do botão de comando Gerar Array :

  Private Sub btnGerarArrayNumeros_Click(sender As Object, e As EventArgs) Handles btnGerarArrayNumeros.Click
        Dim separadores() As String = {",", ".", "!", "?", ";", ":", " "}
        Try
            nomes = txtNomes.Text.Split(separadores, StringSplitOptions.RemoveEmptyEntries)
            numerosString = txtNumeros.Text.Split(separadores, StringSplitOptions.RemoveEmptyEntries)
            numeros = Array.ConvertAll(numerosString, Function(str) Int32.Parse(str))
            HabilitaControlesButton()
            btnGerarArrayNumeros.Enabled = False
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

Dessa forma os arrays serão gerados com os valores informados nos controles TextBox.

Observe que primeiro eu estou gerando dois arrays de string e depois usando o método ConvertAll da classe Array estou convertendo o array de strings numerosString para um array de inteiros em numeros.

Quando o usuário clicar no botão Gerar Array, após a geração dos arrays nomes() e numeros() a rotina HabilitaControlesButton() será chamada para habilitar a propriedade Enabled dos botões.

A seguir temos o código desta rotina:

   Private Sub HabilitaControlesButton()
        For Each P As Control In Controls
            If TypeOf P Is TableLayoutPanel Then
                For Each ctrl As Control In P.Controls
                    If TypeOf ctrl Is Button Then
                        CType(ctrl, Button).Enabled = True
                    End If
                Next
            End If
        Next
    End Sub

Esse código percorre o controle TableLayoutPanel e para cada controle do tipo Button define sua propriedade Enabled como igual a True,

Criamos também uma rotina chamada ajeitaListBox() que recebe um controle button como parâmetro. Seu código esta abaixo:

  Private Sub ajeitaListBox(ctrl As Button)
        lbResultado.Items.Clear()
        lbResultado.Items.Add(ctrl.Tag)
        lbResultado.Items.Add("")
    End Sub

Este código limpa o controle ListBox e inclui um item no controle referente ao texto que esta na propriedade Tag do respectivo controle e a seguir inclui um item vazio.

Usando os operadores LINQ

Agora vamos mostrar a definição e como usar cada operador LINQ. Iremos definir o código no evento Click de cada um dos 9 Buttons.

1- Operador ThenBy

    ''' <summary>
    ''' Executa um ordenação subseqüente dos elementos em uma seqüência em ordem crescente.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnThenBy_Click(sender As Object, e As EventArgs) Handles btnThenBy.Click
        ajeitaListBox(btnThenBy)
        Dim consulta As IEnumerable(Of String) = nomes.OrderBy(Function(nome) nome.Length).ThenBy(Function(nome) nome)
        For Each _nome As String In consulta
            lbResultado.Items.Add(_nome)
        Next
    End Sub

O exemplo esta ordenando o array nomes pelo tamanho do nome - nome.Length

Resultado:

2- Operador Any

    ''' <summary>
    ''' O operador Any numera a seqüência de origem e retorna true se qualquer elemento satisfaz 
    ''' o critério determinado pelo predicado
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnAny_Click(sender As Object, e As EventArgs) Handles btnAny.Click
        ajeitaListBox(btnAny)
        Dim anyNumeros As Boolean = New Integer() {2, 3, 4, 5, 6, 7, 8}.Any(Function(n) n = 10)
        Dim anyNomes As Boolean = New String() {"Paulo", "Jose", "Carlos", "Pedro", "Maria", "Macoratti"}.Any(Function(n) n = "Jose")
        lbResultado.Items.Add(anyNumeros)
        lbResultado.Items.Add(anyNomes)
    End Sub

A primeira consulta verifica se o número 10 esta no array {2, 3, 4, 5, 6, 7, 8} - resultado será False

A segunda consulta verifica se o nome 'Jose' esta no array {"Paulo", "Jose", "Carlos", "Pedro", "Maria", "Macoratti"} - resultado será True

3- Operador Concat

     ''' <summary>
    ''' O operador Concat concatena duas seqüências. 
    ''' Ele retorna todos os elementos da primeiro seqüência, em seguida, todos os elementos da segunda seqüência.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnConcat_Click(sender As Object, e As EventArgs) Handles btnConcat.Click
        ajeitaListBox(btnConcat)
        Dim sequencia2 As Integer() = {555, 666, 777, 888, 999}
        Dim resultado As IEnumerable(Of Integer) = numeros.Concat(sequencia2)
        For Each valor As Integer In resultado
            lbResultado.Items.Add(valor)
        Next
    End Sub

Resultado:

4- Operador Cast

    ''' <summary>
    ''' O operador Cast realiza um cast no elemento da sequencia para um tipo dado.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnCast_Click(sender As Object, e As EventArgs) Handles btnCast.Click
        ajeitaListBox(btnCast)
        ' Cria um ArrayList e incluir itens
        Dim frutas As New System.Collections.ArrayList()
        frutas.Add("Laranja")
        frutas.Add("Manga")
        frutas.Add("Abacate")
        frutas.Add("Banana")
        ' chama o Cast(Of String) para converter os elementos do ArrayList para strings.
        ' Então chama Select() para projetar as string como resultado
        Dim consulta As IEnumerable(Of String) = _
            frutas.Cast(Of String)().Select(Function(fruta) fruta)
        Dim saida As New System.Text.StringBuilder
        For Each fruta As String In consulta
            saida.AppendLine(fruta & ", ")
        Next
        lbResultado.Items.Add(saida)
    End Sub

O operador Cast converte os elementos do ArrayList para String.

O resultado será: Laraja,Manga,Abacate,Banana

5- Operador Distinct

    ''' <summary>
    ''' Elimina valores duplicados em uma sequência
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnDistinct_Click(sender As Object, e As EventArgs) Handles btnDistinct.Click
        ajeitaListBox(btnDistinct)
        Dim consulta = (From s In nomes).Distinct()
        For Each nome As [String] In consulta
            lbResultado.Items.Add(nome)
        Next
    End Sub

O operador Distinct elimina elementos duplicados na sequência.

Resultado:

6- Operador ElementAt

    ''' <summary>
    ''' Retorna um elemento em um dado índice da sequência
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnElementAt_Click(sender As Object, e As EventArgs) Handles btnElementAt.Click
        ajeitaListBox(btnElementAt)
        Dim elemento As Integer = numeros.ElementAt(5)
        lbResultado.Items.Add("O elemento no índice 5 é  :  " & elemento.ToString)
    End Sub

O operador ElementAt e retorna um elemento para um dado índice na sequência.

O resultado será o elemento com índice igual a 5 : 58

7- Operador Repeat

    ''' <summary>
    ''' Repete um valor especificado um determinado número de vezes
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnRepeat_Click(sender As Object, e As EventArgs) Handles btnRepeat.Click
        ajeitaListBox(btnRepeat)
        For Each i As Integer In Enumerable.Repeat(7, 6)
            lbResultado.Items.Add(i & " ")
        Next
    End Sub

O operador Repeat repete um valor especificado um determinado número de vezes.

Resultado :

8- Operador Last

   ''' <summary>
    ''' Retorna o último elemento da sequência
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnLast_Click(sender As Object, e As EventArgs) Handles btnLast.Click
        ajeitaListBox(btnLast)
        Dim ultimoNumero As Integer = numeros.Last()
       Dim ultimoPar As Integer = numeros.Last(Function(n) n Mod 2 = 0)
        lbResultado.Items.Add("Último número : " & ultimoNumero.ToString)
        lbResultado.Items.Add("Último número par : " & ultimoPar.ToString)
    End Sub

O operador Last retorna o último elemento da sequência que atenda o critério definido.

Estamos realizando uma consulta para retonar o último número e o último número par.

Resultado :

9- Operador Except

     ''' <summary>
    ''' Retorna elementos da primeira sequência que  não estão na segunda sequência
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub btnExcept_Click(sender As Object, e As EventArgs) Handles btnExcept.Click
        ajeitaListBox(btnExcept)
        Dim sequencia2 As Integer() = {3, 4, 5, 6, 7, 8}
        lbResultado.Items.Add("sequencia2 = 3, 4, 5, 6, 7, 8")
        Dim diferenca1 As IEnumerable(Of Integer) = numeros.Except(sequencia2)
       Dim diferenca2 As IEnumerable(Of Integer) = sequencia2.Except(numeros)
        lbResultado.Items.Add("Não estão na sequencia2 -----------------")
        For Each i As Integer In diferenca1
            lbResultado.Items.Add(i)
        Next
        lbResultado.Items.Add("Não estão em numeros -----------------")
        For Each i As Integer In diferenca2
            lbResultado.Items.Add(i)
        Next
    End Sub

O operador Except retorna os elementos da primeira sequência que não estão na segunda sequência.

Estamos fazendo duas consultas:  Uma verificando quais elementos da primeira sequência não estão na segunda e na outra invertemos as sequências:

Resultado :

Pegue o projeto completo aqui :  VBNET_LINQ_Operadores.zip

Até o próximo artigo...

João 6:35 Declarou-lhes Jesus. Eu sou o pão da vida; aquele que vem a mim, de modo algum terá fome, e quem crê em mim jamais terá sede.
João 6:36 Mas como já vos disse, vós me tendes visto, e contudo não credes.

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

 

 

             Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter
 

Referências:


José Carlos Macoratti