Type.MakeGenericType(Type[]) Método

Definición

Sustituye los elementos de una matriz de tipos por los parámetros de tipo de la definición de tipo genérico actual y devuelve un objeto Type que representa el tipo construido resultante.Substitutes the elements of an array of types for the type parameters of the current generic type definition and returns a Type object representing the resulting constructed type.

public:
 virtual Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public virtual Type MakeGenericType (params Type[] typeArguments);
abstract member MakeGenericType : Type[] -> Type
override this.MakeGenericType : Type[] -> Type
Public Overridable Function MakeGenericType (ParamArray typeArguments As Type()) As Type

Parámetros

typeArguments
Type[]

Matriz de tipos que se va a sustituir por los parámetros del tipo genérico actual.An array of types to be substituted for the type parameters of the current generic type.

Devoluciones

Objeto Type que representa el tipo construido formado al sustituir los elementos de typeArguments por los parámetros del tipo genérico actual.A Type representing the constructed type formed by substituting the elements of typeArguments for the type parameters of the current generic type.

Excepciones

El tipo actual no representa una definición de un tipo genérico.The current type does not represent a generic type definition. Es decir, IsGenericTypeDefinition devuelve false.That is, IsGenericTypeDefinition returns false.

typeArguments es null.typeArguments is null.

O bien-or- Cualquier elemento de typeArguments es null.Any element of typeArguments is null.

El número de elementos de typeArguments no es el mismo que el número de parámetros de tipo de la definición de tipo genérico actual.The number of elements in typeArguments is not the same as the number of type parameters in the current generic type definition.

O bien-or- Un elemento de typeArguments no satisface las restricciones especificadas para el parámetro de tipo correspondiente del tipo genérico actual.Any element of typeArguments does not satisfy the constraints specified for the corresponding type parameter of the current generic type.

O bien-or- typeArguments contiene un elemento que es un tipo de puntero (IsPointer devuelve true), un tipo por referencia (IsByRef devuelve true) o Void.typeArguments contains an element that is a pointer type (IsPointer returns true), a by-ref type (IsByRef returns true), or Void.

No se admite el método invocado en la clase base.The invoked method is not supported in the base class. Las clases derivadas deben proporcionar una implementación.Derived classes must provide an implementation.

Ejemplos

En el ejemplo siguiente se usa el método MakeGenericType para crear un tipo construido a partir de la definición de tipo genérico para el tipo de Dictionary<TKey,TValue>.The following example uses the MakeGenericType method to create a constructed type from the generic type definition for the Dictionary<TKey,TValue> type. El tipo construido representa una Dictionary<TKey,TValue> de Test objetos con claves de cadena.The constructed type represents a Dictionary<TKey,TValue> of Test objects with string keys.

using namespace System;
using namespace System::Reflection;
using namespace System::Collections::Generic;

namespace Example
{
    public ref class Test
    {
    public:
        static void CreateConstructedType(void)
        {      
            Console::WriteLine("\r\n--- Create a constructed type"
                " from the generic Dictionary`2 type.");
            
            // Create a type object representing 
            // the generic Dictionary`2 type.
            Type^ genericType = Type::GetType(
                "System.Collections.Generic.Dictionary`2");
            if (genericType != nullptr)
            {  
                DisplayTypeInfo(genericType);
            }
            else
            {
                Console::WriteLine("The type is not found");
                return;
            }
            
            // Create an array of types to substitute for the type
            // parameters of Dictionary`2. 
            // The key is of type string, and the type to be 
            // contained in the Dictionary`2 is Test.
            array<Type^>^ typeArgs = {String::typeid, Test::typeid};
            Type^ constructedType = 
                genericType->MakeGenericType(typeArgs);
            DisplayTypeInfo(constructedType);
            
            // Compare the type objects obtained above to type objects
            // obtained using typeof() and GetGenericTypeDefinition().
            Console::WriteLine("\r\n--- Compare types obtained by"
                " different methods:");

            Type^ definedType = Dictionary<String^, Test^>::typeid;
            Console::WriteLine("\tAre the constructed types "
                "equal? {0}", definedType == constructedType);
            Console::WriteLine("\tAre the generic types equal? {0}", 
                definedType->GetGenericTypeDefinition() == genericType);
        }

    private:
        static void DisplayTypeInfo(Type^ typeToDisplay)
        {   
            Console::WriteLine("\r\n{0}", typeToDisplay);
            Console::WriteLine("\tIs this a generic type definition? "
                "{0}", typeToDisplay->IsGenericTypeDefinition);
            Console::WriteLine("\tIs it a generic type? "
                "{0}", typeToDisplay->IsGenericType);
            
            array<Type^>^ typeArguments = 
                typeToDisplay->GetGenericArguments();
            Console::WriteLine("\tList type arguments ({0}):", 
                typeArguments->Length);
            
            for each (Type^ typeArgument in typeArguments)
            {   
                Console::WriteLine("\t\t{0}", typeArgument);
            }
        }
    };
}

int main(void)
{
    Example::Test::CreateConstructedType();
}

/* This example produces the following output:

--- Create a constructed type from the generic Dictionary`2 type.

System.Collections.Generic.Dictionary`2[KeyType,ValueType]
          Is this a generic type definition? True
          Is it a generic type? True
          List type arguments (2):
                     K
                     V

System.Collections.Generic.Dictionary`2[System.String, Test]
          Is this a generic type definition? False
          Is it a generic type? True
          List type arguments (2):
                     System.String
                     Test

--- Compare types obtained by different methods:
          Are the constructed types equal? True
          Are the generic types equal? True
 */
using System;
using System.Reflection;
using System.Collections.Generic;

public class Test
{
    public static void Main()
    {
        Console.WriteLine("\r\n--- Create a constructed type from the generic Dictionary type.");

        // Create a type object representing the generic Dictionary 
        // type, by omitting the type arguments (but keeping the 
        // comma that separates them, so the compiler can infer the
        // number of type parameters).      
        Type generic = typeof(Dictionary<,>);
        DisplayTypeInfo(generic);

        // Create an array of types to substitute for the type
        // parameters of Dictionary. The key is of type string, and
        // the type to be contained in the Dictionary is Test.
        Type[] typeArgs = { typeof(string), typeof(Test) };

        // Create a Type object representing the constructed generic
        // type.
        Type constructed = generic.MakeGenericType(typeArgs);
        DisplayTypeInfo(constructed);

        // Compare the type objects obtained above to type objects
        // obtained using typeof() and GetGenericTypeDefinition().
        Console.WriteLine("\r\n--- Compare types obtained by different methods:");

        Type t = typeof(Dictionary<String, Test>);
        Console.WriteLine("\tAre the constructed types equal? {0}", t == constructed);
        Console.WriteLine("\tAre the generic types equal? {0}", 
            t.GetGenericTypeDefinition() == generic);
    }

    private static void DisplayTypeInfo(Type t)
    {
        Console.WriteLine("\r\n{0}", t);

        Console.WriteLine("\tIs this a generic type definition? {0}", 
            t.IsGenericTypeDefinition);

        Console.WriteLine("\tIs it a generic type? {0}", 
            t.IsGenericType);

        Type[] typeArguments = t.GetGenericArguments();
        Console.WriteLine("\tList type arguments ({0}):", typeArguments.Length);
        foreach (Type tParam in typeArguments)
        {
            Console.WriteLine("\t\t{0}", tParam);
        }
    }
}

/* This example produces the following output:

--- Create a constructed type from the generic Dictionary type.

System.Collections.Generic.Dictionary`2[TKey,TValue]
        Is this a generic type definition? True
        Is it a generic type? True
        List type arguments (2):
                TKey
                TValue

System.Collections.Generic.Dictionary`2[System.String, Test]
        Is this a generic type definition? False
        Is it a generic type? True
        List type arguments (2):
                System.String
                Test

--- Compare types obtained by different methods:
        Are the constructed types equal? True
        Are the generic types equal? True
 */
Imports System.Reflection
Imports System.Collections.Generic

Public Class Test
    Public Shared Sub Main()
        Console.WriteLine(vbCrLf & "--- Create a constructed type from the generic Dictionary type.")

        ' Create a type object representing the generic Dictionary 
        ' type, by omitting the type arguments (but keeping the 
        ' comma that separates them, so the compiler can infer the
        ' number of type parameters).
        Dim generic As Type = GetType(Dictionary(Of ,))
        DisplayTypeInfo(generic)

        ' Create an array of types to substitute for the type
        ' parameters of Dictionary. The key is of type string, and
        ' the type to be contained in the Dictionary is Test.
        Dim typeArgs() As Type = { GetType(String), GetType(Test) }

        ' Create a Type object representing the constructed generic
        ' type.
        Dim constructed As Type = generic.MakeGenericType(typeArgs)
        DisplayTypeInfo(constructed)

        ' Compare the type objects obtained above to type objects
        ' obtained using GetType() and GetGenericTypeDefinition().
        Console.WriteLine(vbCrLf & "--- Compare types obtained by different methods:")

        Dim t As Type = GetType(Dictionary(Of String, Test))
        Console.WriteLine(vbTab & "Are the constructed types equal? " _
            & (t Is constructed))
        Console.WriteLine(vbTab & "Are the generic types equal? " _ 
            & (t.GetGenericTypeDefinition() Is generic))
    End Sub

    Private Shared Sub DisplayTypeInfo(ByVal t As Type)
        Console.WriteLine(vbCrLf & t.ToString())

        Console.WriteLine(vbTab & "Is this a generic type definition? " _ 
            & t.IsGenericTypeDefinition)

        Console.WriteLine(vbTab & "Is it a generic type? " _ 
            & t.IsGenericType)

        Dim typeArguments() As Type = t.GetGenericArguments()
        Console.WriteLine(vbTab & "List type arguments ({0}):", _
            typeArguments.Length)
        For Each tParam As Type In typeArguments       
            Console.WriteLine(vbTab & vbTab & tParam.ToString())
        Next
    End Sub
End Class

' This example produces the following output:
'
'--- Create a constructed type from the generic Dictionary type.
'
'System.Collections.Generic.Dictionary'2[TKey,TValue]
'        Is this a generic type definition? True
'        Is it a generic type? True
'        List type arguments (2):
'                TKey
'                TValue
'
'System.Collections.Generic.Dictionary`2[System.String,Test]
'        Is this a generic type definition? False
'        Is it a generic type? True
'        List type arguments (2):
'                System.String
'                Test
'
'--- Compare types obtained by different methods:
'        Are the constructed types equal? True
'        Are the generic types equal? True

Comentarios

El método MakeGenericType permite escribir código que asigna tipos específicos a los parámetros de tipo de una definición de tipo genérico, con lo que se crea un objeto Type que representa un tipo construido determinado.The MakeGenericType method allows you to write code that assigns specific types to the type parameters of a generic type definition, thus creating a Type object that represents a particular constructed type. Puede utilizar este objeto Type para crear instancias en tiempo de ejecución del tipo construido.You can use this Type object to create run-time instances of the constructed type.

Los tipos construidos con MakeGenericType pueden estar abiertos, es decir, algunos de sus argumentos de tipo pueden ser parámetros de tipo de métodos o tipos genéricos envolventes.Types constructed with MakeGenericType can be open, that is, some of their type arguments can be type parameters of enclosing generic methods or types. Puede usar estos tipos construidos abiertos al emitir ensamblados dinámicos.You might use such open constructed types when you emit dynamic assemblies. Por ejemplo, considere las clases Base y Derived en el código siguiente.For example, consider the classes Base and Derived in the following code.

generic<typename T, typename U>
    public ref class Base { };
generic<typename V>
    public ref class Derived : Base<int, V> { };
public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
    Inherits Base(Of Integer, V)
End Class

Para generar Derived en un ensamblado dinámico, es necesario construir su tipo base.To generate Derived in a dynamic assembly, it is necessary to construct its base type. Para ello, llame al método MakeGenericType en un objeto Type que represente la Basede clase, utilizando los argumentos de tipo genérico Int32 y el parámetro de tipo V de Derived.To do this, call the MakeGenericType method on a Type object representing the class Base, using the generic type arguments Int32 and the type parameter V from Derived. Dado que los tipos y los parámetros de tipo genérico están representados por objetos Type, una matriz que contiene ambos se puede pasar al método MakeGenericType.Because types and generic type parameters are both represented by Type objects, an array containing both can be passed to the MakeGenericType method.

Nota

Un tipo construido como Base<int, V> es útil cuando se emite código, pero no se puede llamar al método MakeGenericType en este tipo porque no es una definición de tipo genérico.A constructed type such as Base<int, V> is useful when emitting code, but you cannot call the MakeGenericType method on this type because it is not a generic type definition. Para crear un tipo construido cerrado del que se puedan crear instancias, primero llame al método GetGenericTypeDefinition para obtener un objeto Type que represente la definición de tipo genérico y, a continuación, llame a MakeGenericType con los argumentos de tipo deseados.To create a closed constructed type that can be instantiated, first call the GetGenericTypeDefinition method to get a Type object representing the generic type definition and then call MakeGenericType with the desired type arguments.

El objeto Type devuelto por MakeGenericType es igual que el Type obtenido mediante una llamada al método GetType del tipo construido resultante, o el método GetType de cualquier tipo construido creado a partir de la misma definición de tipo genérico usando los mismos argumentos de tipo.The Type object returned by MakeGenericType is the same as the Type obtained by calling the GetType method of the resulting constructed type, or the GetType method of any constructed type that was created from the same generic type definition using the same type arguments.

Nota

Una matriz de tipos genéricos no es en sí misma un tipo genérico.An array of generic types is not itself a generic type. No se puede llamar a MakeGenericType en un tipo de matriz, como C<T>[] (Dim ac() As C(Of T) en Visual Basic).You cannot call MakeGenericType on an array type such as C<T>[] (Dim ac() As C(Of T) in Visual Basic). Para construir un tipo genérico cerrado a partir de C<T>[], llame a GetElementType para obtener la definición de tipo genérico C<T>; Llame a MakeGenericType en la definición de tipo genérico para crear el tipo construido; y, por último, llame al método MakeArrayType en el tipo construido para crear el tipo de matriz.To construct a closed generic type from C<T>[], call GetElementType to obtain the generic type definition C<T>; call MakeGenericType on the generic type definition to create the constructed type; and finally call the MakeArrayType method on the constructed type to create the array type. Lo mismo se aplica a los tipos de puntero y ref tipos (ByRef en Visual Basic).The same is true of pointer types and ref types (ByRef in Visual Basic).

Para obtener una lista de las condiciones invariables para los términos usados en la reflexión genérica, vea los comentarios de la propiedad IsGenericType.For a list of the invariant conditions for terms used in generic reflection, see the IsGenericType property remarks.

Tipos anidadosNested Types

Si se define un tipo genérico mediante C#, C++o Visual Basic, los tipos anidados son genéricos.If a generic type is defined using C#, C++, or Visual Basic, then its nested types are all generic. Esto es así incluso si los tipos anidados no tienen ningún parámetro de tipo propio, ya que los tres lenguajes incluyen los parámetros de tipo de los tipos envolventes en las listas de parámetros de tipo de los tipos anidados.This is true even if the nested types have no type parameters of their own, because all three languages include the type parameters of enclosing types in the type parameter lists of nested types. Tenga en cuenta las clases siguientes:Consider the following classes:

generic<typename T> public ref class Outermost
{
public:
    generic<typename U> ref class Inner
    {
    public:
        generic<typename V> ref class Innermost1 {};
        ref class Innermost2 {};
    };
};
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

La lista de parámetros de tipo de la clase anidada Inner tiene dos parámetros de tipo, T y U, el primero de los cuales es el parámetro de tipo de la clase envolvente.The type parameter list of the nested class Inner has two type parameters, T and U, the first of which is the type parameter of its enclosing class. Del mismo modo, la lista de parámetros de tipo de la clase anidada Innermost1 tiene tres parámetros de tipo, T, Uy V, con T y U provienen de sus clases envolventes.Similarly, the type parameter list of the nested class Innermost1 has three type parameters, T, U, and V, with T and U coming from its enclosing classes. La clase anidada Innermost2 tiene dos parámetros de tipo, T y U, que proceden de sus clases envolventes.The nested class Innermost2 has two type parameters, T and U, which come from its enclosing classes.

Si la lista de parámetros del tipo envolvente tiene más de un parámetro de tipo, todos los parámetros de tipo en orden se incluyen en la lista de parámetros de tipo del tipo anidado.If the parameter list of the enclosing type has more than one type parameter, all the type parameters in order are included in the type parameter list of the nested type.

Para construir un tipo genérico a partir de la definición de tipo genérico para un tipo anidado, llame al método MakeGenericType con la matriz formada mediante la concatenación de las matrices de argumentos de tipo de todos los tipos envolventes, empezando por el tipo genérico más externo y finalizando con la matriz de argumentos de tipo del tipo anidado, si tiene parámetros de tipo propios.To construct a generic type from the generic type definition for a nested type, call the MakeGenericType method with the array formed by concatenating the type argument arrays of all the enclosing types, beginning with the outermost generic type, and ending with the type argument array of the nested type itself, if it has type parameters of its own. Para crear una instancia de Innermost1, llame al método MakeGenericType con una matriz que contenga tres tipos, que se asignará a T, U y V. Para crear una instancia de Innermost2, llame al método MakeGenericType con una matriz que contenga dos tipos, que se asignará a T y U.To create an instance of Innermost1, call the MakeGenericType method with an array containing three types, to be assigned to T, U, and V. To create an instance of Innermost2, call the MakeGenericType method with an array containing two types, to be assigned to T and U.

Los lenguajes propagan los parámetros de tipo de los tipos envolventes de este modo, por lo que puede utilizar los parámetros de tipo de un tipo envolvente para definir campos de tipos anidados.The languages propagate the type parameters of enclosing types in this fashion so you can use the type parameters of an enclosing type to define fields of nested types. De lo contrario, los parámetros de tipo no estarán en el ámbito dentro de los cuerpos de los tipos anidados.Otherwise, the type parameters would not be in scope within the bodies of the nested types. Es posible definir tipos anidados sin propagar los parámetros de tipo de los tipos envolventes, mediante la emisión de código en ensamblados dinámicos o mediante Ilasm. exe (ensamblador de IL).It is possible to define nested types without propagating the type parameters of enclosing types, by emitting code in dynamic assemblies or by using the Ilasm.exe (IL Assembler). Considere el siguiente código para el ensamblador de MSIL:Consider the following code for the MSIL assembler:

.class public Outer<T> {  
    .class nested public Inner<U> {  
        .class nested public Innermost {  
        }  
    }  
}  

En este ejemplo, no es posible definir un campo de tipo T o U en la clase Innermost, porque esos parámetros de tipo no están en el ámbito.In this example, it is not possible to define a field of type T or U in class Innermost, because those type parameters are not in scope. El siguiente código de ensamblador define las clases anidadas que se comportan de la C++manera en que lo C#harían si se hubieran definido en, Visual Basic y:The following assembler code defines nested classes that behave the way they would if defined in C++, Visual Basic, and C#:

.class public Outer<T> {  
    .class nested public Inner<T, U> {  
        .class nested public Innermost<T, U, V> {  
        }  
    }  
}  

Puede usar Ildasm. exe (desensamblador de IL) para examinar las clases anidadas definidas en los lenguajes de alto nivel y observar este esquema de nomenclatura.You can use the Ildasm.exe (IL Disassembler) to examine nested classes defined in the high-level languages and observe this naming scheme.

Se aplica a

Consulte también: