Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo fornece comentários complementares à documentação de referência para esta API.
O MakeGenericType método permite que você escreva um código que atribua tipos específicos aos parâmetros de tipo de uma definição de tipo genérico, criando assim um Type objeto que representa um tipo construído específico. Você pode usar esse Type objeto para criar instâncias de runtime do tipo construído.
Os tipos construídos com MakeGenericType podem ser abertos, ou seja, alguns de seus argumentos de tipo podem ser parâmetros de tipo de métodos ou tipos genéricos abrangentes. Você pode usar esses tipos construídos abertos ao criar assemblies dinâmicos. Por exemplo, considere as classes Base e Derived no código a seguir.
public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
type Base<'T, 'U>() = class end
type Derived<'V>() = inherit Base<int, 'V>()
Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
Inherits Base(Of Integer, V)
End Class
Para gerar Derived em um assembly dinâmico, é necessário construir seu tipo base. Para fazer isso, chame o método MakeGenericType em um objeto Type que representa a classe Base, usando argumentos de tipo genérico Int32 e o parâmetro de tipo V de Derived. Como os tipos e os parâmetros de tipo genérico são representados por Type objetos, uma matriz que contém ambos pode ser passada para o MakeGenericType método.
Observação
Um tipo construído como Base<int, V> é útil ao emitir código, mas você não pode chamar o MakeGenericType método nesse tipo porque ele não é uma definição de tipo genérico. Para criar um tipo construído fechado que possa ser instanciado, primeiro chame o GetGenericTypeDefinition método para obter um Type objeto que represente a definição de tipo genérico e, em seguida, chame MakeGenericType com os argumentos de tipo desejados.
O objeto Type retornado por MakeGenericType é o mesmo que Type, obtido ao chamar o método GetType do tipo construído resultante, ou o método GetType de qualquer tipo construído que foi criado a partir da mesma definição de tipo genérico, utilizando os mesmos argumentos de tipo.
Observação
Uma matriz de tipos genéricos não é em si um tipo genérico. Não é possível chamar MakeGenericType um tipo de matriz, como C<T>[] (Dim ac() As C(Of T) no Visual Basic). Para construir um tipo genérico fechado a partir de C<T>[], chame GetElementType para obter a definição de tipo genérico C<T>; chame MakeGenericType na definição de tipo genérico para criar o tipo construído; e, por fim, chame o método MakeArrayType no tipo construído para criar o tipo de matriz. O mesmo vale para tipos de ponteiro e tipos ref (ByRef no Visual Basic).
Para obter uma lista das condições invariantes para termos usados na reflexão genérica, veja as observações da propriedade IsGenericType.
Tipos aninhados
Se um tipo genérico for definido usando C#, C++ou Visual Basic, seus tipos aninhados serão todos genéricos. Isso é verdade mesmo que os tipos aninhados não tenham seus próprios parâmetros de tipo, porque todos os três idiomas incluem os parâmetros de tipo dos tipos envolventes nas listas de parâmetros de tipo dos tipos aninhados. Considere as seguintes classes:
public class Outermost<T>
{
public class Inner<U>
{
public class Innermost1<V> {}
public class Innermost2 {}
}
}
Public Class Outermost(Of T)
Public Class Inner(Of U)
Public Class Innermost1(Of V)
End Class
Public Class Innermost2
End Class
End Class
End Class
A lista de parâmetros de tipo da classe aninhada Inner tem dois parâmetros de tipo, T e U, sendo que o primeiro deles é o parâmetro de tipo de sua classe que a contém. Da mesma forma, a lista de parâmetros de tipo da classe Innermost1 aninhada tem três parâmetros de tipo, TUe , com VT e U vindo de suas classes delimitantes. A classe Innermost2 aninhada tem dois parâmetros de tipo, T e U, que vêm de suas classes envolventes.
Se a lista de parâmetros do tipo delimitante tiver mais de um parâmetro de tipo, todos os parâmetros de tipo na ordem serão incluídos na lista de parâmetros de tipo do tipo aninhado.
Para construir um tipo genérico a partir da definição de tipo genérico para um tipo aninhado, chame o método MakeGenericType usando a matriz formada pela concatenação das matrizes de argumento de tipo de todos os tipos circundantes, começando pelo tipo genérico mais externo e terminando com a matriz de argumento de tipo do próprio tipo aninhado, se tiver parâmetros de tipo próprios. Para criar uma instância de Innermost1, chame o MakeGenericType método com uma matriz contendo três tipos, a ser atribuída a T, U e V. Para criar uma instância de Innermost2, chame o MakeGenericType método com uma matriz contendo dois tipos, a ser atribuída a T e U.
As linguagens propagam os parâmetros de tipo de tipos envolventes dessa forma, permitindo que você utilize os parâmetros de tipo de um tipo envolvente para definir campos de subtipos. Caso contrário, os parâmetros de tipo não estariam no escopo dentro dos corpos dos tipos aninhados. É possível definir tipos aninhados sem propagar os parâmetros de tipo de tipos delimitadores, emitindo código em assemblies dinâmicos ou usando o Ilasm.exe (IL Assembler). Considere o seguinte código para o CIL assembler:
.class public Outer<T> {
.class nested public Inner<U> {
.class nested public Innermost {
}
}
}
Neste exemplo, não é possível definir um campo de tipo T ou U de classe Innermost, porque esses parâmetros de tipo não estão no escopo. O código do assembler a seguir define classes aninhadas que se comportam da maneira que se definidas em C++, Visual Basic e C#:
.class public Outer<T> {
.class nested public Inner<T, U> {
.class nested public Innermost<T, U, V> {
}
}
}
Você pode usar o Ildasm.exe (IL Disassembler) para examinar classes aninhadas definidas nos idiomas de alto nível e observar esse esquema de nomenclatura.