Atenção: esse artigo tem uma palestra complementar. Clique e assista!

Atenção: esse artigo tem um vídeo complementar. Clique e assista!

Do que trata o artigo

Neste artigo serão mostradas várias técnicas para que os dados já carregados para a memória em arrays ou listas de objetos possam ser pesquisados para realizar validações, filtros de dados entre outras tarefas.

Serão demonstrados métodos que facilitam estas tarefas e ajudam o desenvolvedor a aproveitar seu código através do uso de classes genéricas. Você verá desde algumas técnicas de pesquisa tradicionais até as poderosas ferramentas do . NET Framework para economizar seu tempo e seus códigos. Também veremos como a nova linguagem para consulta de dados do Microsoft .NET Framework – LINQ – pode ajudar o desenvolvedor a obter o dado que precisa.

Para que serve

O .NET Framework possui inúmeras ferramentas implementadas para pesquisa e verificação dos dados carregados na memória. Neste artigo serão demonstradas algumas destas ferramentas que estão disponíveis para as coleções usando arrays e listas genéricas.

Em que situação o tema é útil

Seleção e verificação de dados carregados na memória são usadas em várias tarefas como, por exemplo, validar entradas do usuário, verificar códigos digitados ou ainda fazer filtros específicos para algumas coleções de dados. Veremos como podemos realizar esse tipo de tarefa com o C#.

Resumo do DevMan

Através de vários exemplos iniciaremos entendendo como os dados são pesquisados na memória do computador. Basicamente você descobrirá como verificar se um valor está contido dentro de uma lista de dados que poderá ser de vários tipos. Em seguida, verá como fazer isto em uma coleção um pouco mais complexa que usará objetos de dados com vários campos. Com recursos como métodos anônimos, irá realizar pesquisas em listas de objetos com vários atributos de maneira mais rápida. Finalmente será apresentado para a linguagem de consulta de dados incorporada ao .NET Framework: LINQ. Usaremos a versão desta linguagem conhecida como LINQ to Objects direcionada para pesquisa de objetos na memória.

Obter dados que estão armazenados em banco de dados é bastante comum hoje em dia graças a muito utilizada linguagem SQL. Entretanto, existirão casos em que será necessário trabalhar com alguns dados que existem apenas na memória. Uma das situações onde isto pode acontecer é quando se tem uma lista de dados implementada nas regras de negócio do programa e se deseja validar uma entrada que foi feita pelo usuário.

O conhecimento das várias técnicas para seleção de dados permitirá que você economize tempo na implementação de suas rotinas. Uma vez que já existem muitas ferramentas que verificam a existência de determinada informação em uma coleção ou retornam uma lista de valores encontrados que satisfaçam a um determinado critério, o desenvolvedor pode evitar a síndrome de “reinvenção da roda” toda vez que precisar verificar determinados dados.

Muitas vezes, por conhecer poucas ferramentas para pesquisa de dados na memória acaba-se escrevendo uma quantidade desnecessária de código que justamente por ser desestruturado ou pouco planejado, acaba se repetindo em várias partes do programa o que gera confusão e perda de tempo. Então, nem que seja para agilizar o desenvolvimento, é muito bom que se procure conhecer um pouco mais sobre pesquisa de dados.

Usamos os computadores e seus programas por causa da sua grande capacidade de armazenamento de dados e por sua facilidade para encontrá-los. Grande parte do trabalho do programador é localizar, validar ou recuperar porções específicas de dados para realizar tarefas de vários tipos.

Quando se deseja trabalhar com informações que já estão carregadas na memória pode ser necessário que se crie meios para manipular as informações. Considere o código da Listagem 1. Nele teremos uma situação típica das tarefas de programação.

Listagem 1. Exemplo de situação onde a pesquisa de dados é necessária


      1 using System;
      2 
      3 public class Class1
      4 {
      5    public static void Main(string[] args)
      6    {
      7       // cria um array de códigos considerados válidos
      8       int[] ListaDeCodigo = { 33, 250, 21, 99, 42, 22, 64, 98, 32 };
      9       // solicita que o usuário informe um código
     10       Console.WriteLine("Informe um código válido: ");
     11       int CodigoDigitado = Console.Read();
     12    }
     13 }

Trata-se de um pequeno programa do tipo console. Logo na linha 1 declaramos o namespace “System” que contém os elementos necessários da linguagem para este exemplo e depois colocamos a declaração da classe na linha 3. Todos os programas, por mais simples que sejam, consistem de uma classe com pelo menos um método. É o caso do método “Main” que declaramos na linha 5. Este programa mantém uma lista de números inteiros na memória, representado pelo array do tipo “int” que é declarado na linha 8. A tarefa é obter um número inteiro digitado pelo usuário (linhas 10 e 11) e validar se foi digitado um código válido.

Imagine por exemplo um cadastro de usuários em um site onde seja necessário informar um código promocional ou ainda, um número que é previamente definido dentro de uma lista. Como poderíamos implementar a validação deste número?

Existem vários algoritmos de pesquisa. Os mais básicos vão percorrendo a lista contendo os dados até que seja encontrado um valor determinado. Assim que este valor é encontrado a pesquisa é interrompida e se retorna a rotina que o valor foi encontrado. Se a lista inteira for percorrida e nenhum valor for encontrado, significa que a mesma não possui o valor procurado.

O fluxograma da Figura 1 demonstra qual a estrutura deste tipo de algoritmo notando que existem duas condições para sair do fluxo: ou se atinge o fim da lista ou se encontra o valor pesquisado.

Figura 1. Fluxograma de busca básico

Esta é uma forma mais básica de se pesquisar dados. Existem vários outros algoritmos que incluem a ordenação dos dados para facilitar a tarefa; pesquisa binária onde os dados indexados vão sendo divididos em duas partes para que cada vez menos dados sejam pesquisados, e assim por diante. A pesquisa binária é usada principalmente em bancos de dados indexados para diminuir o tempo da consulta.

Não trataremos aqui destes algoritmos, pois não é esse nosso objetivo. Mostraremos os recursos da linguagem C# e do .NET Framework para você fazer seu trabalho rapidamente e principalmente, possa reaproveitar seu código quando for necessário.

Considere que em muitos casos é necessário consultar dados um pouco mais complexos e não simplesmente lista de números ou de palavras. Por exemplo, podemos ter de fazer a pesquisa em uma lista de objetos sendo que estes objetos podem ter um ou mais campos preenchidos. Em alguns casos pode ser necessário pesquisar por um ou vários campos do objeto que está na memória e então o algoritmo e o código para fazer a pesquisa ficarão mais complexos.

A partir da versão 2.0 do .NET Framework a Microsoft incluiu os tipos de dados "generics" (em "System.Collections.Generic") que implementaram as listas dinâmicas. Com isso, várias rotinas para pesquisas também foram acrescentadas permitindo que o desenvolvedor com o conhecimento dos recursos das classes agilizasse as tarefas de busca.

Com a versão 3.5 do .NET Framework uma nova poderosa ferramenta para pesquisa foi incorporada: A linguagem integrada de pesquisa ou simplesmente LINQ (Language INtegrated Query). Neste artigo abordaremos a versão LINQ to Objects que tem por objetivo realizar consulta de listas de objetos existentes na memória sem acessar o disco ou bancos de dados relacionais. Para realizar o trabalho irei desenvolver uma aplicação do tipo Windows Forms bem simples, mas, já incluindo vários elementos de interface com o usuário para facilitar o trabalho.

A versão do Visual Studio utilizada foi a 2010 Professional sendo que você poderá fazer os exemplos na versão 2008 e também usando as versões “Express”. No final do artigo disponibilizei alguns links inclusive para download de uma versão de teste do Visual Studio bem como da novíssima versão Visual Studio 2010 Express Edition.

Também é necessário que você conheça um pouco dos seguintes assuntos:

• Criação de aplicações Windows usando o Visual Studio;

• Criação de classes e programação orientada a objetos;

• Conhecimento do uso das listas genéricas que estão contidos em “System.Collections.Generic”.

Ao longo do artigo, faremos uso de delegates, eventos e métodos anônimos - parte importante do .NET Framework e da construção de classes. Todos eles estão muito bem documentados pelo Visual Studio e em muitos outros exemplos pela Internet. Como seu uso não é muito comum para alguns programadores o código pode parecer um pouco estranho, mas, faça os testes, leia mais sobre o assunto e aos poucos, você poderá familiarizar-se com estes recursos.

Métodos de pesquisa de List<T>

A partir da versão 2.0 do framework foram incorporadas as listas genéricas onde a declaração de uma coleção de dados de qualquer tipo ficou bem mais fácil. Este tipo de lista além de oferecer uma maneira simples de trabalhar com coleções dinâmicas de dados, também possui um grande número de recursos para realizar pesquisas nos dados contidos dentro da mesma.

Nota: Quando usamos arrays clássicos, o array tem um tamanho fixo sendo mais difícil alterar a sua dimensão inicial. Com as listas genéricas, o tamanho é dinâmico podendo ser alterado facilmente através da inclusão ou exclusão de elementos.

Ao contrário dos arrays clássicos onde apenas um método para busca está disponível e mesmo assim apenas para alguns tipos de dados, com as listas genéricas vários métodos estão disponíveis para pesquisa desde a versão 2.0 do framework.

Além de serem mais indicados por causa destas funcionalidades você pode facilmente converter uma array tradicional em uma lista bastando para isso passar o array existente para o construtor da lista como no exemplo a seguir:

  // instancia uma lista baseada em um vetor
  List<int> lista = new List<int>( new int[] { 1,2,3,4 } );

Na Tabela 1 coloquei os principais métodos usados por esta classe para você fazer pesquisas.

Método

Função

Tipo de dado retornado

Contains

Verifica se um elemento existe dentro da coleção de objetos.

...

Quer ler esse conteúdo completo? Tenha acesso completo