Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Os genéricos permitem adaptar um método, classe, estrutura ou interface ao tipo de dados preciso sobre o qual ele atua. Por exemplo, em vez de usar a Hashtable classe, que permite que chaves e valores sejam de qualquer tipo, você pode usar a Dictionary<TKey,TValue> classe genérica e especificar os tipos permitidos para a chave e o valor. Entre os benefícios dos genéricos estão o aumento da reutilização do código e a segurança do tipo.
Definir e utilizar genéricos
Genéricos são classes, estruturas, interfaces e métodos que têm espaços reservados (parâmetros de tipo) para um ou mais dos tipos que armazenam ou usam. Uma classe de coleção genérica pode usar um parâmetro type como um espaço reservado para o tipo de objetos que ela armazena. Os parâmetros de tipo aparecem como os tipos de seus campos e os tipos de parâmetros de seus métodos. Um método genérico pode usar seu parâmetro type como o tipo de seu valor de retorno ou como o tipo de um de seus parâmetros formais.
O código a seguir ilustra uma definição de classe genérica simples.
public class SimpleGenericClass<T>
{
public T Field;
}
Public Class SimpleGenericClass(Of T)
Public Field As T
End Class
Ao criar uma instância de uma classe genérica, você especifica os tipos reais para substituir os parâmetros de tipo. Isso estabelece uma nova classe genérica, referida como uma classe genérica construída, com os tipos escolhidos substituídos em todos os lugares em que os parâmetros de tipo aparecem. O resultado é uma classe segura de tipos que é adaptada à sua escolha de tipos, como o código a seguir ilustra.
public static void Main()
{
SimpleGenericClass<string> g = new SimpleGenericClass<string>();
g.Field = "A string";
//...
Console.WriteLine($"SimpleGenericClass.Field = \"{g.Field}\"");
Console.WriteLine($"SimpleGenericClass.Field.GetType() = {g.Field.GetType().FullName}");
}
Public Shared Sub Main()
Dim g As New SimpleGenericClass(Of String)
g.Field = "A string"
'...
Console.WriteLine("SimpleGenericClass.Field = ""{0}""", g.Field)
Console.WriteLine("SimpleGenericClass.Field.GetType() = {0}", g.Field.GetType().FullName)
End Sub
Terminologia
Os seguintes termos são usados para discutir genéricos no .NET:
Uma definição de tipo genérica é uma declaração de classe, estrutura ou interface que funciona como um modelo, com espaços reservados para os tipos que ela pode conter ou usar. Por exemplo, a System.Collections.Generic.Dictionary<TKey,TValue> classe pode conter dois tipos: chaves e valores. Como uma definição de tipo genérica é apenas um modelo, não é possível criar instâncias de uma classe, estrutura ou interface que seja uma definição de tipo genérica.
Parâmetros de tipo genéricos, ou parâmetros de tipo, são os espaços reservados em uma definição genérica de tipo ou método. O System.Collections.Generic.Dictionary<TKey,TValue> tipo genérico tem dois parâmetros de tipo,
TKeyeTValue, que representam os tipos de suas chaves e valores.Um tipo genérico construído, ou tipo construído, é o resultado da especificação de tipos para os parâmetros de tipo genéricos de uma definição de tipo genérico.
Um argumento de tipo genérico é qualquer tipo que é substituído por um parâmetro de tipo genérico.
O termo geral tipo genérico inclui tipos construídos e definições genéricas de tipo.
A covariância e a contravariância de parâmetros de tipo genéricos permitem que você use tipos genéricos construídos cujos argumentos de tipo são mais derivados (covariância) ou menos derivados (contravariância) do que um tipo construído de destino. Covariância e contravariância são coletivamente referidas como variância. Para obter mais informações, consulte Covariância e contravariância.
Restrições são limites colocados em parâmetros de tipo genéricos. Por exemplo, você pode limitar um parâmetro type a tipos que implementam a System.Collections.Generic.IComparer<T> interface genérica, para garantir que instâncias do tipo possam ser ordenadas. Você também pode restringir parâmetros de tipo a tipos que têm uma classe base específica, que têm um construtor sem parâmetros ou que são tipos de referência ou tipos de valor. Os usuários do tipo genérico não podem substituir argumentos de tipo que não satisfaçam as restrições.
Uma definição de método genérico é um método com duas listas de parâmetros: uma lista de parâmetros de tipo genéricos e uma lista de parâmetros formais. Os parâmetros de tipo podem aparecer como o tipo de retorno ou como os tipos dos parâmetros formais, como mostra o código a seguir.
T MyGenericMethod<T>(T arg) { T temp = arg; //... return temp; }Function MyGenericMethod(Of T)(ByVal arg As T) As T Dim temp As T = arg '... Return temp End FunctionOs métodos genéricos podem aparecer em tipos genéricos ou não genéricos. É importante notar que um método não é genérico apenas porque pertence a um tipo genérico, ou mesmo porque tem parâmetros formais cujos tipos são os parâmetros genéricos do tipo anexo. Um método é genérico somente se tiver sua própria lista de parâmetros de tipo. No código a seguir, apenas o método
Gé genérico.class A { T G<T>(T arg) { T temp = arg; //... return temp; } } class MyGenericClass<T> { T M(T arg) { T temp = arg; //... return temp; } }Class A Function G(Of T)(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function End Class Class MyGenericClass(Of T) Function M(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function End Class
Vantagens e desvantagens dos genéricos
Há muitas vantagens em usar coleções genéricas e delegados:
Segurança de tipos. Os genéricos transferem o fardo da segurança de tipo de você para o compilador. Não há necessidade de escrever código para testar o tipo de dados correto porque ele é imposto em tempo de compilação. A necessidade de conversão de tipos e a possibilidade de erros em tempo de execução são reduzidas.
Menos código e o código é mais fácil de reutilizar. Não há necessidade de herdar de um tipo base e substituir membros. Por exemplo, o LinkedList<T> está pronto para uso imediato. Por exemplo, você pode criar uma lista vinculada de cadeias de caracteres com a seguinte declaração de variável:
LinkedList<string> llist = new LinkedList<string>();Dim llist As New LinkedList(Of String)()Melhor desempenho. Os tipos de coleção genéricos geralmente têm melhor desempenho para armazenar e manipular tipos de valor porque não há necessidade de encaixotar os tipos de valor.
Os delegados genéricos permitem retornos de chamada seguros em termos de tipos, sem a necessidade de criar várias classes de delegados. Por exemplo, o Predicate<T> delegado genérico permite que você crie um método que implementa seus próprios critérios de pesquisa para um tipo específico e use seu método com métodos do Array tipo , como Find, FindLaste FindAll.
Os genéricos simplificam o código gerado dinamicamente. Quando você usa genéricos com código gerado dinamicamente, não é necessário gerar o tipo. Isso aumenta o número de cenários nos quais você pode usar métodos dinâmicos leves em vez de gerar assemblies inteiros. Para obter mais informações, consulte Como definir e executar métodos dinâmicos e DynamicMethod.
Seguem-se algumas limitações dos genéricos:
Os tipos genéricos podem ser derivados da maioria das classes base, como MarshalByRefObject (e as restrições podem ser usadas para exigir que os parâmetros de tipo genéricos derivem de classes base como MarshalByRefObject). No entanto, o .NET não oferece suporte a tipos genéricos ligados ao contexto. Um tipo genérico pode ser derivado de ContextBoundObject, mas tentar criar uma instância desse tipo causa um TypeLoadException.
As enumerações não podem ter parâmetros de tipo genéricos. Uma enumeração pode ser genérica apenas incidentalmente (por exemplo, porque é aninhada em um tipo genérico que é definido usando Visual Basic, C# ou C++). Para obter mais informações, consulte "Enumerações" em Common Type System.
Os métodos dinâmicos leves não podem ser genéricos.
No Visual Basic, C# e C++, um tipo aninhado que está incluído em um tipo genérico não pode ser instanciado, a menos que os tipos tenham sido atribuídos aos parâmetros de tipo de todos os tipos de inclusão. Outra maneira de dizer isso é que, em reflexão, um tipo aninhado que é definido usando essas linguagens inclui os parâmetros de tipo de todos os seus tipos de inclusão. Isso permite que os parâmetros de tipo dos tipos envolventes sejam usados nas definições de membros de um tipo aninhado. Para obter mais informações, consulte "Tipos aninhados" em MakeGenericType.
Observação
Um tipo aninhado que é definido emitindo código em um conjunto dinâmico ou usando o Ilasm.exe (IL Assembler) não é necessário para incluir os parâmetros de tipo de seus tipos de inclusão; no entanto, se não os incluir, os parâmetros de tipo não estarão no escopo na classe aninhada.
Para obter mais informações, consulte "Tipos aninhados" em MakeGenericType.
Biblioteca de classes e suporte a idiomas
O .NET fornece várias classes de coleção genéricas nos seguintes namespaces:
O System.Collections.Generic namespace contém a maioria dos tipos de coleção genéricos fornecidos pelo .NET, como as classes List<T> e Dictionary<TKey,TValue> genéricas.
O System.Collections.ObjectModel namespace contém tipos de coleção genéricos adicionais, como a ReadOnlyCollection<T> classe genérica, que são úteis para expor modelos de objeto aos usuários de suas classes.
Interfaces genéricas para implementar comparações de classificação e igualdade são fornecidas no System namespace, juntamente com tipos de delegados genéricos para manipuladores de eventos, conversões e predicados de pesquisa.
O System.Numerics namespace fornece interfaces genéricas para funcionalidade matemática (disponível no .NET 7 e versões posteriores). Para obter mais informações, consulte Matemática genérica.
O suporte para genéricos foi adicionado ao System.Reflection namespace para examinar tipos e métodos genéricos, ao System.Reflection.Emit para emitir assemblies dinâmicos que contêm tipos e métodos genéricos, e ao System.CodeDom para gerar gráficos de origem que incluem genéricos.
O common language runtime fornece novos opcodes e prefixos para suportar tipos genéricos em Common Intermediate Language (CIL), incluindo Stelem, Ldelem, Unbox_Any, Constrained, e Readonly.
Visual C++, C# e Visual Basic fornecem suporte completo para definir e usar genéricos. Para obter mais informações sobre suporte a idiomas, consulte Tipos genéricos no Visual Basic, Introdução aos genéricos e Visão geral dos genéricos no Visual C++.
Tipos aninhados e genéricos
Um tipo aninhado em um tipo genérico pode depender dos parâmetros de tipo do tipo genérico que o inclui. O common language runtime considera os tipos aninhados como genéricos, mesmo que eles não tenham parâmetros de tipo genéricos próprios. Ao criar uma instância de um tipo aninhado, você deve especificar argumentos de tipo para todos os tipos genéricos incluídos.
Artigos relacionados
| Título | Descrição |
|---|---|
| Coleções genéricas no .NET | Descreve classes de coleção genéricas e outros tipos genéricos no .NET. |
| Delegados genéricos para manipular matrizes e listas | Descreve delegados genéricos para conversões, predicados de pesquisa e ações a serem executadas em elementos de uma matriz ou coleção. |
| Matemática genérica | Descreve como você pode executar operações matemáticas genericamente. |
| Interfaces Genéricas | Descreve interfaces genéricas que fornecem funcionalidade comum entre famílias de tipos genéricos. |
| Covariância e Contravariância | Descreve a covariância e contravariância em parâmetros de tipo genéricos. |
| Tipos de coleção comumente usados | Fornece informações resumidas sobre as características e cenários de uso dos tipos de coleção no .NET, incluindo tipos genéricos. |
| Quando usar coleções genéricas | Descreve regras gerais para determinar quando usar tipos de coleção genéricos. |
| Como: Definir um tipo genérico com emissão de reflexão | Explica como gerar assemblies dinâmicos que incluem tipos e métodos genéricos. |
| Tipos genéricos no Visual Basic | Descreve o recurso de genéricos para utilizadores do Visual Basic, incluindo tópicos de orientação para usar e definir tipos genéricos. |
| Introdução aos Genéricos | Fornece uma visão geral da definição e do uso de tipos genéricos para usuários C#. |
| Visão geral de genéricos no Visual C++ | Descreve o recurso genéricos para usuários C++, incluindo as diferenças entre genéricos e modelos. |