Compartir a través de


Reflexión y tipos genéricos

Desde el punto de vista de la reflexión, la diferencia entre un tipo genérico y un tipo normal es que los tipos genéricos llevan asociado un conjunto de parámetros de tipo (si se trata de una definición de tipo genérico) o bien argumentos de tipo (si se trata de un tipo construido). Los métodos genéricos se diferencian de los métodos normales en ese mismo sentido.

Hay dos claves para entender la forma en que la reflexión controla los tipos y métodos genéricos:

  • Las instancias de la clase Type representan los parámetros de tipo de las definiciones de tipos genéricos y métodos genéricos.

    NotaNota

    Muchas propiedades y métodos de Type presentan un comportamiento distinto cuando un objeto Type representa un parámetro de tipo genérico.Estas diferencias se describen en la documentación relativa a los temas sobre propiedades y métodos.Por ejemplo, vea IsAutoClass y DeclaringType.Además, algunos miembros sólo son válidos cuando un objeto Type representa un parámetro de tipo genérico.Por ejemplo, vea GetGenericTypeDefinition.

  • Si una instancia de Type representa un tipo genérico, entonces incluye una matriz de tipos que representa los parámetros de tipo (para definiciones de tipos genéricos) o los argumentos de tipo (para tipos construidos). Esto mismo es cierto para una instancia de la clase MethodInfo que representa un método genérico.

La reflexión proporciona métodos de las clases Type y MethodInfo que le permiten obtener acceso a la matriz de parámetros de tipo y le permiten determinar si una instancia de Type representa un parámetro de tipo o un tipo real.

Para obtener un ejemplo de código donde se muestran los métodos que aquí se describen, vea Cómo: Examinar y crear instancias de tipos genéricos mediante la reflexión.

En la siguiente descripción se asume que el lector está familiarizado con la terminología relativa a los genéricos, como la diferencia que existe entre argumentos y parámetros de tipo, y entre tipos construidos abiertos o cerrados. Para obtener más información, vea Genéricos en .NET Framework.

Esta información general consta de las siguientes secciones:

  • Determinar si se trata de un tipo o método genérico

  • Generar tipos genéricos cerrados

  • Examinar argumentos de tipo y parámetros de tipo

  • Invariables

  • Temas relacionados

Determinar si se trata de un tipo o método genérico

Cuando utilice la reflexión para examinar un tipo desconocido, representado por una instancia de Type, utilice la propiedad IsGenericType para determinar si el tipo desconocido es genérico. Si el tipo es genérico, devuelve true. Del mismo modo, cuando examine un método desconocido, representado por una instancia de la clase MethodInfo, utilice la propiedad IsGenericMethod para determinar si el método es genérico.

Determinar si se trata de una definición de tipo o método genérico

Utilice la propiedad IsGenericTypeDefinition para determinar si un objeto Type representa una definición de tipo genérico y utilice el método IsGenericMethodDefinition para determinar si un objeto MethodInfo representa una definición de método genérico.

Las definiciones de tipos y métodos genéricos son las plantillas a partir de las que se crean los tipos de los que se pueden crear instancias. Los tipos genéricos de la biblioteca de clases de .NET Framework, como Dictionary<TKey, TValue>, son definiciones de tipos genéricos.

Determinar si el tipo o método está abierto o cerrado

Un tipo o método genérico está cerrado si los tipos a partir de los que pueden crearse instancias se han sustituido para todos sus parámetros de tipo, incluidos todos los parámetros de tipo de todos los tipos envolventes. Sólo se puede crear una instancia de un tipo genérico si está cerrado. La propiedad Type.ContainsGenericParameters devuelve true si un tipo está abierto. En el caso de los métodos, el método MethodInfo.ContainsGenericParameters realiza la misma función.

Volver al principio

Generar tipos genéricos cerrados

Una vez que disponga de una definición de tipo o método genérico, utilice el método MakeGenericType para crear un tipo genérico cerrado o el método MakeGenericMethod para crear un objeto MethodInfo para un método genérico cerrado.

Obtener la definición de tipo o método genérico

Si dispone de un tipo o método genérico abierto que no sea una definición de tipo o método genérico, no podrá crear instancias del mismo y no podrá suministrar los parámetros de tipo de falten. Debe disponer de una definición de tipo o método genérico. Utilice el método GetGenericTypeDefinition para obtener la definición de tipo genérico o el método GetGenericMethodDefinition para obtener la definición de método genérico.

Por ejemplo, si dispone de un objeto Type que representa Dictionary<int, string> (Dictionary(Of Integer, String) en Visual Basic) y desea crear el tipo Dictionary<string, MyClass>, puede utilizar el método GetGenericTypeDefinition para obtener un Type que represente Dictionary<TKey, TValue> y, a continuación, utilizar el método MakeGenericType para generar un Type que represente Dictionary<int, MyClass>.

Para obtener un ejemplo de un tipo genérico abierto que no sea un tipo genérico, vea "Parámetro de tipo o argumento de tipo" más adelante en este tema.

Volver al principio

Examinar argumentos de tipo y parámetros de tipo

Utilice el método Type.GetGenericArguments para obtener una matriz de objetos Type que represente los parámetros de tipo o argumentos de tipo de un tipo genérico, y utilice el método MethodInfo.GetGenericArguments para hacer lo mismo con un método genérico.

Cuando se sabe que un objeto Type representa un parámetro de tipo, hay muchas cuestiones adicionales a las que puede responder la reflexión; se puede determinar el origen del parámetro de tipo, su posición y sus restricciones.

Parámetro de tipo o argumento de tipo

Para determinar si un elemento determinado de la matriz es un parámetro de tipo o un argumento de tipo, utilice la propiedad IsGenericParameter. La propiedad IsGenericParameter es true si el elemento es un parámetro de tipo.

Un tipo genérico puede estar abierto sin necesidad de ser una definición de tipo genérico, en cuyo caso dispondrá de una mezcla de argumentos de tipo y parámetros de tipo. Por ejemplo, en el siguiente código, la clase D se deriva de un tipo creado mediante la sustitución del primer parámetro de tipo de D por el segundo parámetro de tipo de 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> {};

Si obtiene un objeto Type que representa D<V, W> y utiliza la propiedad BaseType para obtener su tipo base, el tipo type B<int, V> resultante estará abierto, pero no será una definición de tipo genérico.

Origen de un parámetro genérico

Un parámetro de tipo genérico podría proceder del tipo que está examinando, de un tipo envolvente o de un método genérico. Puede determinar el origen del parámetro de tipo genérico tal y como se muestra a continuación:

  • En primer lugar, utilice la propiedad DeclaringMethod para determinar si el parámetro de tipo procede de un método genérico. Si el valor de la propiedad no es una referencia nula (Nothing en Visual Basic), entonces el origen es un método genérico.

  • Si el origen no es un método genérico, utilice la propiedad DeclaringType para determinar el tipo genérico al que el parámetro de tipo genérico pertenece.

Si el parámetro de tipo pertenece a un método genérico, la propiedad DeclaringType devolverá el tipo que declaró el método genérico, lo que resulta irrelevante.

Posición de un parámetro genérico

En situaciones excepcionales, es necesario determinar la posición de un parámetro de tipo en la lista de parámetros de tipo de su clase declarante. Por ejemplo, supongamos que dispone de un objeto Type que representa el tipo B<int, V> del ejemplo anterior. El método GetGenericArguments proporciona una lista de argumentos de tipo y cuando se examina V se pueden utilizar las propiedades DeclaringMethod y DeclaringType para detectar su procedencia. A continuación, se puede utilizar la propiedad GenericParameterPosition para determinar su posición en la lista de parámetros de tipo donde se definió. En este ejemplo, V está en posición 0 (cero) en la lista de parámetros de tipo donde se definió.

Tipo base y restricciones de interfaz

Utilice el método GetGenericParameterConstraints para obtener la restricción de tipo base y las restricciones de interfaz de un parámetro de tipo. El orden de los elementos de la matriz no es significativo. Un elemento representa una restricción de interfaz si se trata de un tipo de interfaz.

Atributos de parámetros genéricos

La propiedad GenericParameterAttributes obtiene un valor GenericParameterAttributes que indica la varianza (covarianza o contravarianza) y las restricciones especiales de un parámetro de tipo.

Covarianza y contravarianza

Para determinar si un parámetro de tipo es covariante o contravariante, aplique la máscara GenericParameterAttributes.VarianceMask al valor GenericParameterAttributes devuelto por la propiedad GenericParameterAttributes. Si el resultado es GenericParameterAttributes.None, el parámetro de tipo es invariable. Vea Covarianza y contravarianza en genéricos.

Restricciones especiales

Para determinar las restricciones especiales de un parámetro de tipo, aplique la máscara GenericParameterAttributes.SpecialConstraintMask al valor GenericParameterAttributes devuelto por la propiedad GenericParameterAttributes. Si el resultado es GenericParameterAttributes.None, no existen restricciones especiales. Un parámetro de tipo puede restringirse para que sea un tipo de referencia, un tipo de valor que no acepte valores NULL y que disponga de un constructor predeterminado.

Volver al principio

Invariables

Para obtener una tabla de las condiciones invariables para términos comunes en la reflexión de tipos genéricos, vea Type.IsGenericType. Para obtener términos adicionales relativos a los métodos genéricos, vea MethodInfo.IsGenericMethod.

Volver al principio

Temas relacionados

Título

Descripción

Cómo: Examinar y crear instancias de tipos genéricos mediante la reflexión

Muestra cómo utilizar las propiedades y métodos de Type y MethodInfo para examinar los tipos genéricos.

Genéricos en .NET Framework

Describe la característica de genéricos y cómo se admite en .NET Framework.

Cómo: Definir un tipo genérico con la emisión de la reflexión

Explica cómo utilizar la emisión de reflexión para generar los tipos genéricos en ensamblados dinámicos.

Ver información de tipos

Describe la clase Type y proporciona ejemplos de código que muestran cómo utilizar Type con diversas clases de reflexión para obtener información sobre constructores, métodos, campos, propiedades y eventos.

Volver al principio