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.
Observação
Este artigo fornece observações complementares à documentação de referência para esta API.
O MakeGenericType método permite que você escreva código que atribui tipos específicos aos parâmetros de tipo de uma definição de tipo genérica, criando assim um Type objeto que representa um determinado tipo construído. Pode usar este Type objeto para criar instâncias em tempo de execução do tipo criado.
Os tipos construídos com MakeGenericType podem ser abertos, ou seja, alguns de seus argumentos de tipo podem ser parâmetros de tipo de inclusão de métodos ou tipos genéricos. Você pode usar esses tipos construídos abertos quando emite 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 uma montagem dinâmica, é necessário construir seu tipo de base. Para fazer isso, chame o método MakeGenericType em um objeto Type que representa a classe Base, usando os argumentos Int32 de tipo genérico e o parâmetro de tipo V de Derived. Como os tipos e os parâmetros de tipo genéricos são representados por Type objetos, uma matriz contendo 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 não é uma definição de tipo genérica. 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érica e, em seguida, chame MakeGenericType com os argumentos de tipo desejados.
O Type objeto retornado por MakeGenericType é o mesmo que o Type obtido chamando o GetType método do tipo construído resultante, ou o GetType método de qualquer tipo construído que foi criado a partir da mesma definição de tipo genérica usando os mesmos argumentos de tipo.
Observação
Uma matriz de tipos genéricos não é, em si mesma, um tipo genérico. Você não pode 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, finalmente, chame o método MakeArrayType no tipo construído para criar o tipo de array. O mesmo acontece com tipos de ponteiro e ref tipos (ByRef no Visual Basic).
Para obter uma lista das condições invariáveis para termos usados em reflexão genérica, consulte as observações da propriedade IsGenericType.
Tipos aninhados
Se um tipo genérico é definido usando C#, C++ ou Visual Basic, então seus tipos aninhados são todos genéricos. Mesmo que os tipos aninhados não tenham parâmetros de tipo próprios, isso é verdade porque todos os três idiomas incluem os parâmetros de tipo dos tipos que os contêm 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 Inner aninhada tem dois parâmetros de tipo, T e Uo primeiro dos quais é o parâmetro de tipo de sua classe de delimitação. Da mesma forma, a lista de parâmetros de tipo da classe Innermost1 aninhada tem três parâmetros de tipo, T, U, e V, com T e U provenientes de suas classes anexas. A classe Innermost2 aninhada tem dois parâmetros de tipo, T e U, que vêm de suas classes de encerramento.
Se a lista de parâmetros do tipo envolvente tiver mais de um parâmetro de tipo, todos os parâmetros de tipo, na ordem correta, 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 MakeGenericType método com a matriz formada pela concatenação das matrizes de argumento de tipo de todos os tipos que o delimitam, começando com o tipo genérico mais externo e terminando com a matriz de argumento de tipo do próprio tipo aninhado, se ele 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 serem atribuídos a T, U e V. Para criar uma instância de Innermost2, chame o MakeGenericType método com uma matriz contendo dois tipos, a serem atribuídos a T e U.
As linguagens propagam os parâmetros de tipo dos tipos envolventes desta forma para que se possa usar os parâmetros de tipo de um tipo envolvente para definir campos de tipos aninhados. Caso contrário, os parâmetros de tipo não estariam no escopo dentro das estruturas dos tipos aninhados. É possível definir tipos aninhados sem propagar os parâmetros de tipo de tipos envolventes, emitindo código em assemblies dinâmicos ou usando o Ilasm.exe (IL Assembler). Considere o seguinte código para o assemblador CIL:
.class public Outer<T> {
.class nested public Inner<U> {
.class nested public Innermost {
}
}
}
Neste exemplo, não é possível definir um campo do tipo T ou U em classe Innermost, porque esses parâmetros de tipo não estão no escopo. O código assembler a seguir define classes aninhadas que se comportam da maneira que se fossem 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 nas linguagens de alto nível e observar esse esquema de nomenclatura.