Reflexão e tipos genéricosReflection and Generic Types

Do ponto de vista da reflexão, a diferença entre um tipo genérico e um tipo comum é que um tipo genérico está associado a ele um conjunto de parâmetros de tipo (se for uma definição de tipo genérico) ou argumentos de tipo (se for um tipo construído).From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). Um método genérico é diferente de um método comum da mesma maneira.A generic method differs from an ordinary method in the same way.

Há duas chaves para entender como a reflexão trata tipos e métodos genéricos:There are two keys to understanding how reflection handles generic types and methods:

  • Os parâmetros de tipo de definições de tipo genérico e definições de método genérico são representadas por instâncias da classe Type.The type parameters of generic type definitions and generic method definitions are represented by instances of the Type class.

    Observação

    Muitas propriedades e métodos de Type têm um comportamento diferente quando um objeto Type representa um parâmetro de tipo genérico.Many properties and methods of Type have different behavior when a Type object represents a generic type parameter. Essas diferenças são documentadas nos tópicos de propriedade e método.These differences are documented in the property and method topics. Por exemplo, veja IsAutoClass e DeclaringType.For example, see IsAutoClass and DeclaringType. Além disso, alguns membros são válidos somente quando um objeto Type representa um parâmetro de tipo genérico.In addition, some members are valid only when a Type object represents a generic type parameter. Por exemplo, veja GetGenericTypeDefinition.For example, see GetGenericTypeDefinition.

  • Se uma instância do Type representa um tipo genérico, ela inclui uma matriz de tipos que representam os parâmetros de tipo (para definições de tipo genérico) ou os argumentos de tipo (para tipos construídos).If an instance of Type represents a generic type, then it includes an array of types that represent the type parameters (for generic type definitions) or the type arguments (for constructed types). O mesmo é verdadeiro para uma instância da classe MethodInfo que representa um método genérico.The same is true of an instance of the MethodInfo class that represents a generic method.

A reflexão fornece métodos de Type e MethodInfo que permitem a você acessar a matriz de parâmetros de tipo e determinar se uma instância de Type representa um parâmetro de tipo ou um tipo real.Reflection provides methods of Type and MethodInfo that allow you to access the array of type parameters, and to determine whether an instance of Type represents a type parameter or an actual type.

Para obter o código de exemplo que demonstra os métodos discutidos aqui, consulte Como examinar tipos genéricos e criar instâncias deles com a reflexão.For example code demonstrating the methods discussed here, see How to: Examine and Instantiate Generic Types with Reflection.

A discussão a seguir pressupõe familiaridade com a terminologia de genéricos, como a diferença entre os parâmetros e argumentos de tipo e tipos construídos abertos ou fechados.The following discussion assumes familiarity with the terminology of generics, such as the difference between type parameters and arguments and open or closed constructed types. Para obter mais informações, consulte Genéricos.For more information, see Generics.

Este é um tipo ou um método genérico?Is This a Generic Type or Method?

Quando usar a reflexão para examinar um tipo desconhecido, representado por uma instância de Type, use a propriedade IsGenericType para determinar se o tipo desconhecido é genérico.When you use reflection to examine an unknown type, represented by an instance of Type, use the IsGenericType property to determine whether the unknown type is generic. Ele retornará true se o tipo for genérico.It returns true if the type is generic. Da mesma forma, quando você examinar um método desconhecido, representado por uma instância da classe MethodInfo, use a propriedade IsGenericMethod para determinar se o método é genérico.Similarly, when you examine an unknown method, represented by an instance of the MethodInfo class, use the IsGenericMethod property to determine whether the method is generic.

Esta é uma definição de tipo ou método genérico?Is This a Generic Type or Method Definition?

Use a propriedade IsGenericTypeDefinition para determinar se um objeto Type representa uma definição de tipo genérico e use o método IsGenericMethodDefinition para determinar se um MethodInfo representa uma definição de método genérico.Use the IsGenericTypeDefinition property to determine whether a Type object represents a generic type definition, and use the IsGenericMethodDefinition method to determine whether a MethodInfo represents a generic method definition.

As definições de tipo e método genéricos são os modelos dos quais os tipos instanciáveis são criados.Generic type and method definitions are the templates from which instantiable types are created. Os tipos genéricos na biblioteca de classes do .NET Framework, como Dictionary<TKey,TValue>, são definições de tipo genérico.Generic types in the .NET Framework class library, such as Dictionary<TKey,TValue>, are generic type definitions.

O tipo ou o método é aberto ou fechado?Is the Type or Method Open or Closed?

Um tipo ou método genérico será fechado se os tipos instanciáveis tiverem sido substituídos para todos os seus parâmetros de tipo, incluindo todos os parâmetros de tipo de todos os tipos delimitadores.A generic type or method is closed if instantiable types have been substituted for all its type parameters, including all the type parameters of all enclosing types. Você poderá criar uma instância de um tipo genérico somente se ele for fechado.You can only create an instance of a generic type if it is closed. A propriedade Type.ContainsGenericParameters retornará true se um tipo for aberto.The Type.ContainsGenericParameters property returns true if a type is open. Para métodos, o método MethodBase.ContainsGenericParameters executa a mesma função.For methods, the MethodBase.ContainsGenericParameters method performs the same function.

Gerando tipos genéricos fechadosGenerating Closed Generic Types

Quando você tiver uma definição de método ou tipo genérico, use o método MakeGenericType para criar um tipo genérico fechado ou o método MakeGenericMethod para criar um MethodInfo para um método genérico fechado.Once you have a generic type or method definition, use the MakeGenericType method to create a closed generic type or the MakeGenericMethod method to create a MethodInfo for a closed generic method.

Obtendo a definição do tipo ou método genéricoGetting the Generic Type or Method Definition

Se você tiver um método ou tipo genérico aberto que não seja uma definição de método ou tipo genérico, não poderá criar instâncias dele e não poderá fornecer os parâmetros de tipo que estão faltando.If you have an open generic type or method that is not a generic type or method definition, you cannot create instances of it and you cannot supply the type parameters that are missing. Você deve ter uma definição de tipo ou método genérico.You must have a generic type or method definition. Use o método GetGenericTypeDefinition para obter a definição de tipo genérico ou o método GetGenericMethodDefinition para obter a definição de método genérico.Use the GetGenericTypeDefinition method to obtain the generic type definition or the GetGenericMethodDefinition method to obtain the generic method definition.

Por exemplo, se você tiver um objeto Type representando Dictionary<int, string> (Dictionary(Of Integer, String) no Visual Basic) e desejar criar o tipo Dictionary<string, MyClass>, poderá usar o método GetGenericTypeDefinition para obter um Type representando Dictionary<TKey, TValue> e, em seguida, usar o método MakeGenericType para produzir um Type representando Dictionary<int, MyClass>.For example, if you have a Type object representing Dictionary<int, string> (Dictionary(Of Integer, String) in Visual Basic) and you want to create the type Dictionary<string, MyClass>, you can use the GetGenericTypeDefinition method to get a Type representing Dictionary<TKey, TValue> and then use the MakeGenericType method to produce a Type representing Dictionary<int, MyClass>.

Para obter um exemplo de um tipo genérico aberto que não é um tipo genérico, consulte "Parâmetro de tipo ou argumento de tipo" posteriormente neste tópico.For an example of an open generic type that is not a generic type, see "Type Parameter or Type Argument" later in this topic.

Examinando os parâmetros de tipo e os argumentos de tipoExamining Type Arguments and Type Parameters

Use o método Type.GetGenericArguments para obter uma matriz de objetos Type que representam os parâmetros de tipo ou os argumentos de tipo de um tipo genérico e use o método MethodInfo.GetGenericArguments para fazer o mesmo para um método genérico.Use the Type.GetGenericArguments method to obtain an array of Type objects that represent the type parameters or type arguments of a generic type, and use the MethodInfo.GetGenericArguments method to do the same for a generic method.

Uma vez que você souber que um objeto Type representa um parâmetro de tipo, há muitas perguntas adicionais que a reflexão pode responder.Once you know that a Type object represents a type parameter, there are many additional questions reflection can answer. Você pode determinar a origem do parâmetro de tipo, sua posição e suas restrições.You can determine the type parameter's source, its position, and its constraints.

Parâmetro de tipo ou argumento de tipoType Parameter or Type Argument

Para determinar se um elemento específico da matriz é um parâmetro de tipo ou um argumento de tipo, use a propriedade IsGenericParameter.To determine whether a particular element of the array is a type parameter or a type argument, use the IsGenericParameter property. A propriedade IsGenericParameter será true se o elemento for um parâmetro de tipo.The IsGenericParameter property is true if the element is a type parameter.

Um tipo genérico pode ser aberto sem ser uma definição de tipo genérico, nesse caso, ele tem uma mistura de argumentos de tipo e parâmetros de tipo.A generic type can be open without being a generic type definition, in which case it has a mixture of type arguments and type parameters. Por exemplo, no código a seguir, a classe D deriva de um tipo criado substituindo o primeiro parâmetro de tipo de D pelo segundo parâmetro de tipo de B.For example, in the following code, class D derives from a type created by substituting the first type parameter of D for the second type parameter of B.

class B<T, U> {}  
class D<V, W> : B<int, V> {}  
Class B(Of T, U)  
End Class  
Class D(Of V, W)  
    Inherits B(Of Integer, V)  
End Class  
generic<typename T, typename U> ref class B {};  
generic<typename V, typename W> ref class D : B<int, V> {};  

Se você obtiver um objeto Type representando D<V, W> e usar a propriedade BaseType para obter seu tipo base, o type B<int, V> resultante será aberto, mas não será uma definição de tipo genérico.If you obtain a Type object representing D<V, W> and use the BaseType property to obtain its base type, the resulting type B<int, V> is open, but it is not a generic type definition.

Origem de um parâmetro genéricoSource of a Generic Parameter

Um parâmetro de tipo genérico pode vir do tipo sendo examinado, de um tipo delimitador ou de um método genérico.A generic type parameter might come from the type you are examining, from an enclosing type, or from a generic method. Você pode determinar a origem do parâmetro de tipo genérico da seguinte maneira:You can determine the source of the generic type parameter as follows:

  • Primeiro, use a propriedade DeclaringMethod para determinar se o parâmetro de tipo é proveniente de um método genérico.First, use the DeclaringMethod property to determine whether the type parameter comes from a generic method. Se o valor da propriedade não for uma referência nula (Nothing no Visual Basic), a origem será um método genérico.If the property value is not a null reference (Nothing in Visual Basic), then the source is a generic method.

  • Se a origem não for um método genérico, use a propriedade DeclaringType para determinar o tipo genérico ao qual o parâmetro de tipo genérico pertence.If the source is not a generic method, use the DeclaringType property to determine the generic type the generic type parameter belongs to.

Se o parâmetro de tipo pertencer a um método genérico, a propriedade DeclaringType retornará o tipo que declarou o método genérico, o que é irrelevante.If the type parameter belongs to a generic method, the DeclaringType property returns the type that declared the generic method, which is irrelevant.

Posição de um parâmetro genéricoPosition of a Generic Parameter

Em raras situações, é necessário determinar a posição de um parâmetro de tipo na lista de parâmetros de tipo de sua classe declarante.In rare situations, it is necessary to determine the position of a type parameter in the type parameter list of its declaring class. Por exemplo, suponha que você tenha um objeto Type representando o tipo B<int, V> do exemplo anterior.For example, suppose you have a Type object representing the B<int, V> type from the preceding example. O método GetGenericArguments fornece uma lista de argumentos de tipo e ao examinar V você pode usar as propriedades DeclaringMethod e DeclaringType para descobrir de onde ele vem.The GetGenericArguments method gives you a list of type arguments, and when you examine V you can use the DeclaringMethod and DeclaringType properties to discover where it comes from. Você pode usar a propriedade GenericParameterPosition para determinar sua posição na lista de parâmetros de tipo em que foi definido.You can then use the GenericParameterPosition property to determine its position in the type parameter list where it was defined. Neste exemplo, V está na posição 0 (zero) na lista de parâmetros de tipo em que foi definido.In this example, V is at position 0 (zero) in the type parameter list where it was defined.

Tipo base e restrições de interfaceBase Type and Interface Constraints

Use o método GetGenericParameterConstraints para obter a restrição do tipo base e as restrições de interface de um parâmetro de tipo.Use the GetGenericParameterConstraints method to obtain the base type constraint and interface constraints of a type parameter. A ordem dos elementos da matriz não é significativa.The order of the elements of the array is not significant. Um elemento representará uma restrição de interface se ele for um tipo de interface.An element represents an interface constraint if it is an interface type.

Atributos de parâmetro genéricoGeneric Parameter Attributes

A propriedade GenericParameterAttributes obtém um valor GenericParameterAttributes que indica a variância (covariância ou contravariância) e as restrições especiais de um parâmetro de tipo.The GenericParameterAttributes property gets a GenericParameterAttributes value that indicates the variance (covariance or contravariance) and the special constraints of a type parameter.

Covariância e contravariânciaCovariance and Contravariance

Para determinar se um parâmetro de tipo é covariante ou contravariante, aplique a máscara GenericParameterAttributes.VarianceMask ao valor GenericParameterAttributes retornado pela propriedade GenericParameterAttributes.To determine whether a type parameter is covariant or contravariant, apply the GenericParameterAttributes.VarianceMask mask to the GenericParameterAttributes value that is returned by the GenericParameterAttributes property. Se o resultado for GenericParameterAttributes.None, o parâmetro de tipo será invariável.If the result is GenericParameterAttributes.None, the type parameter is invariant. Consulte Covariância e contravariância.See Covariance and Contravariance.

Restrições especiaisSpecial Constraints

Para determinar as restrições especiais de um parâmetro de tipo, aplique a máscara GenericParameterAttributes.SpecialConstraintMask ao valor GenericParameterAttributes retornado pela propriedade GenericParameterAttributes.To determine the special constraints of a type parameter, apply the GenericParameterAttributes.SpecialConstraintMask mask to the GenericParameterAttributes value that is returned by the GenericParameterAttributes property. Se o resultado for GenericParameterAttributes.None, não haverá nenhuma restrição especial.If the result is GenericParameterAttributes.None, there are no special constraints. Um parâmetro de tipo pode ser restringido para ser um tipo de referência, para ser um tipo de valor não nulo e para ter um construtor sem parâmetros.A type parameter can be constrained to be a reference type, to be a non-nullable value type, and to have a parameterless constructor.

InvariáveisInvariants

Para obter uma tabela de condições invariáveis para termos comuns na reflexão de tipos genéricos, consulte Type.IsGenericType.For a table of the invariant conditions for common terms in reflection for generic types, see Type.IsGenericType. Para encontrar termos adicionais relacionados aos métodos genéricos, consulte MethodBase.IsGenericMethod.For additional terms relating to generic methods, see MethodBase.IsGenericMethod.

TítuloTitle DescriçãoDescription
Como examinar tipos genéricos e criar instâncias deles com a reflexãoHow to: Examine and Instantiate Generic Types with Reflection Mostra como usar as propriedades e os métodos de Type e MethodInfo para examinar tipos genéricos.Shows how to use the properties and methods of Type and MethodInfo to examine generic types.
GenéricosGenerics Descreve o recurso de genéricos e como ele tem suporte no .NET Framework.Describes the generics feature and how it is supported in the .NET Framework.
Como definir um tipo genérico com a emissão de reflexãoHow to: Define a Generic Type with Reflection Emit Mostra como usar a emissão de reflexão para gerar tipos genéricos nos assemblies dinâmicos.Shows how to use reflection emit to generate generic types in dynamic assemblies.
Exibindo informações de tipoViewing Type Information Descreve a classe Type e fornece exemplos de código que ilustram como usar Type com várias classes de reflexão para obter informações sobre construtores, métodos, campos, propriedades e eventos.Describes the Type class and provides code examples that illustrate how to use Type with various reflection classes to obtain information about constructors, methods, fields, properties, and events.