Usando Generics para trabalhar com Coleções no Visual Studio.NET 2005

 

Neste artigo vamos falar de uma das grandes inovações do Visual Studio .NET 2005, as coleções genéricas (Generics). Usando Generics podemos criar coleções fortemente tipadas com uma simples linha de código, com isso podemos aproveitar dos recursos do IntelliSense que conseguirá interpretar em tempo de design os tipos de dados e chaves das coleções criadas.

 

Novo Conceito

 

Antes de começarmos a implementação e uso dos Generics, é importante dedicarmos alguns minutos para analisar porque essa nova funcionalidade foi criada. Generics veio com a necessidade de trabalharmos com vários tipos de objetos de uma maneira genérica. Desde o Visual Basic 6.0 já tínhamos essa funcionalidade, e podíamos armazenar objetos de vários tipos em nossas chamadas Collections. Por outro lado, essas classes Collections possuíam algumas limitações. Por exemplo, imagine que seja necessário armazenar uma classe Funcionario em uma Collection. O código abaixo mostra como é feito:

 

Pripriedades da Classe Funcionario

Public ID As Integer

Public Nome As String

Public Sobrenome As String

Public Salario As Currency

 

Adicionando na Collection

Dim Funcionarios As New Collection

Dim Func As Funcionário

 

Set Func = New Funcionario

Func.ID = 5638

Func.Nome = "Daniel"

Func.Sobrenome = "Bragagnolo"

Func.Salario = 1000

 

Funcionarios.Add Func, Func.ID

 

Na primeira etapa do código acima temos as propriedades da classe Funcionario com seus tipos. Uma instancia de Funcionario é criada e populada com dados. Finalmente, Funcionario é adicionado na coleção(Funcionarios) especificando a propriedade ID como chave.

O código abaixo mostra como Funcionario pode ser resgatado da coleção:

 

Dim Func As Employee

Set Func = Funcionarios(5638)

 

Agora, vamos examinar as limitações dessa Collection. Primeiro, no cenário acima, é sabido e muito provável que você queira armazenar apenas objetos do tipo Funcionario na coleção Funcionarios, porem não há nada que impeça o armazenamento de N outros tipos de objetos nessa mesma coleção. Além disso, quando se tenta recuperar qualquer item dessa coleção, também não há nada que nos informe qual tipo de objeto estamos resgatando. Por exemplo, o código abaixo será compilado sem erros:

 

Dim s As String

s = Funcionarios(5638)

 

É obvio que isso retornará um erro de execução em runtime, mas apenas em runtime, em design time não há nada que impeça essa declaração. Sem contar que não há como ter o suporte do IntelliSense para este caso.

 

Framework 1.0/1.1 Collections

 

Com a vinda do Visual Studio.Net e da criação da plataforma .Net Framework 1.0/1.1 resolveu-se alguns dos problemas com Collections simplesmente oferecendo mais alguns tipos de Coleções. Importando o Namespace System.Collections é possível fazer uso de Collections do tipo ArrayList, BitArray, HashTable, Queue, SortedList, e Stack. Na tabela abaixo pode-se observar o cenário de uso para cada uma dessas novas coleções:

 

Collection Classes

Nome da Collection

Cenário de Uso

ArrayList

Criar arrays que podem crescer dinamicamente.

BitArray

Armazenar arrays do tipo Boolean (true/false).

HashTable

Muito parecido com as Collections do Visual Basic 6.

Com esse tipo é possível localizar valores usando uma chave.

Porem, essa chave e o valor poderá ser de qualquer tipo.

SortedList

Este tipo é muito similar ao HashTable, exceto pelo fato de que as

chaves são sempre ordenadas.

Queue

Essa coleção prove acesso a objetos baseada no conceito first in, first out.

Stack

Essa coleção prove acesso a objetos baseada no conceito first in, last out.

 

O .NET Framework 1.0/1.1 resolveu os problemas de flexibilidade e as limitações do Visual Basic 6.0, porém, o que se faz necessário é um tipo de Collection onde se possa informar por exemplo que toda a chave deve ser uma String e todos os dados devem ser do tipo Funcionario.

Com o .NET Framework 2.0 isso foi resolvido usando Generics.

 

Framework 2.0 Generics

 

Com Generics os tipos são estritamente checados, há uma melhor funcionalidade do IntelliSense, além de uma melhor performance. Resumindo, o Generics veio para resolver todos os problemas com Collections existentes no passado.

Atualmente, ao criarmos uma instancia de uma Generic Collection nós passamos informações para que essa collection possa ser fortemente tipada. Isso nos oferece inúmeras vantagens, incluindo segurança, maior reusabilidade de código, IntelliSense, e uma melhor performance. Alem disso, o .NET Framework 2.0 nos prove as novas Generic Collection mas ainda continua fornecendo acessibilidade as classes Collection da versão 1.0/1.1. Não há nada nessa nova versão que force o uso de Generics.

 

Consumindo Generics

 

Para usarmos as novas classes Generics começamos importando o namespace System.Collections.Generic. Isso nos garantirá acesso as classes to Dictionary, List, Queue, SortedDictionary, e Stack.

Abaixo temos um exemplo de uso do Generics:

 

Dim Funcionarios As New Dictionary(Of Int32, Funcionario)

Dim Func As Funcionario

Func = New Funcionario

Func.ID = 5638

Func.Nome = "Daniel"

Func.Sobrenome = "Bragagnolo"

Func.Salario = 1000

 

Funcionarios.Add(Func.ID, Func)

 

Dim Func2 As Funcionario

Func2 = Funcionarios.Item(5638)

 

Dim s As String

s = Funcionarios.Item(5638) ' Neste caso, essa linha gerará um erro de sintaxe.

Funcionarios.Item(5638).Nome = "João"

 

Se olharmos bem ao longo do código, perceberemos alguns fatos interessantes. Veja que para instanciar um objeto Generics usamos este código.

 

Dim Funcionarios As New Dictionary(Of String, Funcionario)

 

Isso significa que criaremos um Dictionary, onde sua chave deverá ser uma String, e seu conteúdo um objeto do tipo Funcionario. Qualquer tentativa de armazenar outro tipo de objeto resultará em um erro de compilação. Essa é uma das diferenças, usando Generics se tentarmos armazenar um tipo diferente resultará em um erro de compilação e não mais um erro de execução.

Além do mais, temos agora total apoio do IntelliSense para os tipos em nossa collection. Olhando a figura abaixo se pode perceber que o Visual Studio sabe que o dicionário armazena somente Classes Funcionario, e as propriedades da classe podemos ver no IntelliSense:

 

IntelliSense funcionando para o nosso objeto.

 

Como podemos ver é bem fácil de se usar Generics, e o resultado é um tipo de coleção fortemente tipada, com o IntelliSense trabalhando a nosso favor, além de um ganho de performance e reusabilidade de código.

 

Conclusão

 

Generics nos oferece inúmeras vantagens para trabalharmos com coleções de objetos fortemente tipadas, onde podemos tratar os erros em tempo de design. Este tipo de coleção fortemente tipada faz com que o IntelliSense possa trabalhar a nosso favor, onde o mesmo consegue entender as propriedades do objeto armazenado, impedindo o armazenamento de objetos com tipos inadequados.