Tipos genéricos no Visual Basic (Visual Basic)
Um tipo genérico é um único elemento de programação que se adapta para executar a mesma funcionalidade para uma variedade de tipos de dados. Ao definir uma classe ou procedimento genérico, não é necessário definir uma versão separada para cada tipo de dados para o qual talvez queira executar essa funcionalidade.
Uma analogia é um conjunto de chave de fenda com cabeças removíveis. Você inspeciona o parafuso que precisa girar e seleciona a cabeça correta para esse parafuso (ranhurado, cruzado, estrelado). Depois de inserir a cabeça correta na alça da chave de fenda, você executa exatamente a mesma função com a chave de fenda, ou seja, girar o parafuso.
Ao definir um tipo genérico, você o parametriza com um ou mais tipos de dados. Isso permite que o código de uso adapte os tipos de dados às suas necessidades. Seu código pode declarar vários elementos de programação diferentes do elemento genérico, cada um atuando em um conjunto diferente de tipos de dados. Mas todos os elementos declarados executam a lógica idêntica, independentemente dos tipos de dados que estão usando.
Por exemplo, talvez você queira criar e usar uma classe de fila que opere em um tipo de dados específico, como String
. Você pode declarar essa classe de System.Collections.Generic.Queue<T>, como mostra o exemplo a seguir.
Public stringQ As New System.Collections.Generic.Queue(Of String)
Agora você pode usar stringQ
para trabalhar exclusivamente com String
valores. Como stringQ
é específico para String
em vez de ser generalizado para Object
valores, você não tem vinculação tardia ou conversão de tipo. Isso economiza tempo de execução e reduz erros em tempo de execução.
Para obter mais informações sobre como usar um tipo genérico, consulte Como usar uma classe genérica.
Exemplo de uma classe genérica
O exemplo a seguir mostra uma definição de esqueleto de uma classe genérica.
Public Class classHolder(Of t)
Public Sub processNewItem(ByVal newItem As t)
Dim tempItem As t
' Insert code that processes an item of data type t.
End Sub
End Class
No esqueleto anterior, t
é um parâmetro type, ou seja, um espaço reservado para um tipo de dados que você fornece quando declara a classe. Em outra parte do código, você pode declarar várias versões do fornecendo vários tipos de classHolder
dados para t
. O exemplo a seguir mostra duas dessas declarações.
Public integerClass As New classHolder(Of Integer)
Friend stringClass As New classHolder(Of String)
As instruções anteriores declaram classes construídas, nas quais um tipo específico substitui o parâmetro type. Essa substituição é propagada por todo o código dentro da classe construída. O exemplo a seguir mostra a aparência do processNewItem
procedimento no integerClass
.
Public Sub processNewItem(ByVal newItem As Integer)
Dim tempItem As Integer
' Inserted code now processes an Integer item.
End Sub
Para obter um exemplo mais completo, consulte Como definir uma classe que pode fornecer funcionalidade idêntica em diferentes tipos de dados.
Elementos de programação elegíveis
Você pode definir e usar classes genéricas, estruturas, interfaces, procedimentos e delegados. Observe que o .NET Framework define várias classes genéricas, estruturas e interfaces que representam elementos genéricos comumente usados. O System.Collections.Generic namespace fornece dicionários, listas, filas e pilhas. Antes de definir seu próprio elemento genérico, verifique se ele já está disponível em System.Collections.Generic.
Os procedimentos não são tipos, mas você pode definir e usar procedimentos genéricos. Consulte Procedimentos genéricos no Visual Basic.
Vantagens dos Tipos Genéricos
Um tipo genérico serve de base para declarar vários elementos de programação diferentes, cada um dos quais opera em um tipo de dados específico. As alternativas a um tipo genérico são:
Um único tipo operando no
Object
tipo de dados.Um conjunto de versões específicas do tipo do tipo, cada versão codificada individualmente e operando em um tipo de dados específico, como
String
,Integer
ou um tipo definido pelo usuário, comocustomer
.
Um tipo genérico tem as seguintes vantagens sobre estas alternativas:
Segurança do tipo. Os tipos genéricos impõem a verificação de tipo em tempo de compilação. Tipos baseados em
Object
aceitar qualquer tipo de dados, e você deve escrever código para verificar se um tipo de dados de entrada é aceitável. Com tipos genéricos, o compilador pode detetar incompatibilidades de tipo antes do tempo de execução.Desempenho. Os tipos genéricos não precisam encaixotar e descompactar dados, porque cada um é especializado para um tipo de dados. Operações baseadas em
Object
tipos de dados de entrada de caixa obrigatórios para convertê-los eObject
descompactar dados destinados à saída. Boxe e unboxing reduzem o desempenho.Os tipos baseados em
Object
também são tardios, o que significa que o acesso aos seus membros requer código extra em tempo de execução. Isso também reduz o desempenho.Consolidação de código. O código num tipo genérico tem de ser definido apenas uma vez. Um conjunto de versões específicas do tipo de um tipo deve replicar o mesmo código em cada versão, com a única diferença sendo o tipo de dados específico para essa versão. Com tipos genéricos, as versões específicas do tipo são todas geradas a partir do tipo genérico original.
Reutilização de código. O código que não depende de um determinado tipo de dados pode ser reutilizado com vários tipos de dados se for genérico. Muitas vezes, você pode reutilizá-lo mesmo com um tipo de dados que você não previu originalmente.
Suporte IDE. Quando você usa um tipo construído declarado a partir de um tipo genérico, o ambiente de desenvolvimento integrado (IDE) pode fornecer mais suporte enquanto você está desenvolvendo seu código. Por exemplo, o IntelliSense pode mostrar as opções específicas do tipo para um argumento para um construtor ou método.
Algoritmos Genéricos. Algoritmos abstratos que são independentes do tipo são bons candidatos para tipos genéricos. Por exemplo, um procedimento genérico que classifica itens usando a IComparable interface pode ser usado com qualquer tipo de dados que implemente IComparableo .
Restrições
Embora o código em uma definição de tipo genérica deva ser o mais independente de tipo possível, talvez seja necessário exigir um determinado recurso de qualquer tipo de dados fornecido ao seu tipo genérico. Por exemplo, se você quiser comparar dois itens com a finalidade de classificar ou agrupar, seu tipo de dados deve implementar a IComparable interface. Você pode impor esse requisito adicionando uma restrição ao parâmetro type.
Exemplo de uma restrição
O exemplo a seguir mostra uma definição de esqueleto de uma classe com uma restrição que requer o argumento type para implementar IComparable.
Public Class itemManager(Of t As IComparable)
' Insert code that defines class members.
End Class
Se o código subsequente tentar construir uma classe a partir do fornecimento de itemManager
um tipo que não implementa IComparable, o compilador sinaliza um erro.
Tipos de restrições
Sua restrição pode especificar os seguintes requisitos em qualquer combinação:
O argumento type deve implementar uma ou mais interfaces
O argumento type deve ser do tipo de, ou herdar de, no máximo uma classe
O argumento type deve expor um construtor sem parâmetros acessível ao código que cria objetos a partir dele
O argumento type deve ser um tipo de referência ou deve ser um tipo de valor
Se precisar impor mais de um requisito, use uma lista de restrições separada por vírgulas dentro de chaves ({ }
). Para exigir um construtor acessível, inclua a palavra-chave New Operator na lista. Para exigir um tipo de referência, você inclui a Class
palavra-chave, para exigir um tipo de valor, você inclui a Structure
palavra-chave.
Para obter mais informações sobre restrições, consulte Lista de tipos.
Exemplo de restrições múltiplas
O exemplo a seguir mostra uma definição de esqueleto de uma classe genérica com uma lista de restrições no parâmetro type. No código que cria uma instância dessa classe, o argumento type deve implementar as IComparable interfaces e IDisposable , ser um tipo de referência e expor um construtor sem parâmetros acessível.
Public Class thisClass(Of t As {IComparable, IDisposable, Class, New})
' Insert code that defines class members.
End Class
Termos Importantes
Os tipos genéricos introduzem e utilizam os seguintes termos:
Tipo Genérico. Uma definição de uma classe, estrutura, interface, procedimento ou delegado para o qual você fornece pelo menos um tipo de dados ao declará-lo.
Digite Parâmetro. Em uma definição de tipo genérica, um espaço reservado para um tipo de dados que você fornece quando declara o tipo.
Digite argumento. Um tipo de dados específico que substitui um parâmetro type quando você declara um tipo construído de um tipo genérico.
Restrição. Uma condição em um parâmetro type que restringe o argumento type que você pode fornecer para ele. Uma restrição pode exigir que o argumento type implemente uma interface específica, seja ou herde de uma classe específica, tenha um construtor sem parâmetros acessível ou seja um tipo de referência ou um tipo de valor. Você pode combinar essas restrições, mas pode especificar no máximo uma classe.
Tipo Construído. Uma classe, estrutura, interface, procedimento ou delegado declarado de um tipo genérico fornecendo argumentos de tipo para seus parâmetros de tipo.