Nota: este método es nuevo en la versión 2.0 de .NET Framework.
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.
Espacio de nombres: System
Ensamblado: mscorlib (en mscorlib.dll)
Visual Basic (Declaración)
Public Overridable Function MakeGenericType ( _
ParamArray typeArguments As Type() _
) As Type
Dim instance As Type
Dim typeArguments As Type()
Dim returnValue As Type
returnValue = instance.MakeGenericType(typeArguments)
public virtual Type MakeGenericType (
params Type[] typeArguments
)
public:
virtual Type^ MakeGenericType (
... array<Type^>^ typeArguments
)
public Type MakeGenericType (
Type[] typeArguments
)
public function MakeGenericType (
... typeArguments : Type[]
) : Type
Parámetros
- typeArguments
Matriz de tipos que se va a sustituir por los parámetros del tipo genérico actual.
Valor devuelto
Objeto Type que representa el tipo construido formado al sustituir los elementos de typeArguments por los parámetros del tipo genérico actual.
| Tipo de excepción | Condición |
|---|
InvalidOperationException | El tipo actual no representa una definición de tipo genérico. Es decir, IsGenericTypeDefinition devuelve false. |
ArgumentNullException |
El valor de typeArguments es referencia de objeto null (Nothing en Visual Basic). O bien Algún elemento de typeArguments es referencia de objeto null (Nothing en Visual Basic). |
ArgumentException | El número de elementos de typeArguments no coincide con el número de parámetros de tipo de la definición de tipo genérico actual. O bien Algún elemento de typeArguments no satisface las restricciones especificadas para el parámetro de tipo correspondiente del tipo genérico actual. |
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, por lo que crea un objeto Type que representa un tipo construido determinado. Puede utilizar este objeto Type para crear instancias en tiempo de ejecución del tipo construido.
Los tipos construidos con el método MakeGenericType pueden ser abiertos; es decir, algunos de sus argumentos de tipo pueden ser parámetros de tipo de métodos o tipos genéricos envolventes. Podría utilizar dichos tipos construidos abiertos al emitir ensamblados dinámicos. Por ejemplo, considere las clases Base y Derived en el código siguiente.
Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
Inherits Base(Of Integer, V)
End Class
public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
generic<typename T, typename U>
public ref class Base { };
generic<typename V>
public ref class Derived : Base<int, V> { };
Para generar la clase Derived en un ensamblado dinámico, es necesario construir su tipo base. Para ello, llame al método MakeGenericType en un objeto Type que represente la clase Base y utilice los argumentos de tipo genérico Int32 y el parámetro de tipo V de la clase Derived. Dado que los tipos y los parámetros de tipo genérico se representan mediante objetos Type, se puede pasar al método MakeGenericType una matriz que contenga los dos.
Nota |
|---|
| Un tipo construido como Base<int, V> resulta útil al emitir código, pero no se puede llamar al método MakeGenericType en este tipo porque no es una definición de tipo genérico. Para crear un tipo construido cerrado del que se pueden crear instancias, primero llame al método GetGenericTypeDefinition a fin de obtener un objeto Type que represente una definición de tipo genérico y, luego, llame al método MakeGenericType con los argumentos de tipo deseados. |
El objeto Type devuelto por el método MakeGenericType es el mismo que el objeto Type que se obtiene al llamar al método GetType del tipo construido resultante o al método GetType de cualquier tipo construido que se haya creado a partir de la misma definición de tipo genérico con el mismo tipo de argumentos.
Nota |
|---|
| Una matriz de tipos genéricos no es propiamente un tipo genérico. No se puede llamar al método MakeGenericType en un tipo de matriz como C<T>[] (Dim ac() As C(Of T) en Visual Basic). Si desea 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. Lo anterior también se aplica a los tipos de puntero y a los tipos ref (ByRef en Visual Basic). |
Si desea obtener una lista de las condiciones invariables para términos que se utilizan en la reflexión genérica, vea los comentarios de la propiedad IsGenericType.
Tipos anidados
Si se define un tipo genérico utilizando C# , C++ o Visual Basic, todos sus tipos anidados son genéricos. Esto se cumple incluso cuando los tipos anidados no poseen ningún parámetro de tipo propio, porque 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. Considere las clases siguientes:
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
public class Outermost<T>
{
public class Inner<U>
{
public class Innermost1<V> {}
public class Innermost2 {}
}
}
generic<typename T> public ref class Outermost
{
public:
generic<typename U> ref class Inner
{
public:
generic<typename V> ref class Innermost1 {};
ref class Innermost2 {};
};
};
La lista de parámetros de tipo de la clase anidada Inner tiene dos parámetros de tipo, T y U, siendo el primero el parámetro de tipo de su clase envolvente. De manera similar, la lista de parámetros de tipo de la clase anidada Innermost1 tiene tres parámetros de tipo, T, U y V, proviniendo T y U de sus clases envolventes. La clase anidada Innermost2 tiene dos parámetros de tipo, T y U, que provienen de sus clases envolventes.
Si la lista de parámetros del tipo envolvente tiene más de un parámetro de tipo, todos los parámetros de tipo se incluyen en orden en la lista de parámetros de tipo del tipo anidado.
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 al concatenar las matrices de argumentos de todos los tipos envolventes, comenzando por el tipo genérico exterior y finalizando por la matriz de argumentos del tipo anidado si éste tiene sus propios parámetros de tipo. Para crear una instancia de Innermost1, llame al método MakeGenericType con una matriz que contenga tres tipos, que se van a 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 van a asignar a T y U.
El lenguaje propaga los parámetros de tipo de los tipos envolventes de esta manera, de modo que puede utilizar los parámetros de tipo de un tipo envolvente para definir los campos de los tipos anidados. De lo contrario, los parámetros de tipo no quedarán dentro del ámbito en los tipos anidados. Es posible definir tipos anidados sin propagar los parámetros de tipo de los tipos envolventes mediante la emisión de código en los ensamblados dinámicos o utilizando Ensamblador de MSIL (Ilasm.exe). Consideremos el código siguiente para el ensamblador de MSIL:
.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, puesto que esos parámetros de tipo están fuera de ámbito. En el código de ensamblador siguiente se definen clases anidadas que se comportan igual que si estuvieran definidas en C++, Visual Basic y C#:
.class public Outer<T> {
.class nested public Inner<T, U> {
.class nested public Innermost<T, U, V> {
}
}
}
Puede utilizar Desensamblador de MSIL (Ildasm.exe) para examinar clases anidadas definidas en los lenguajes de alto nivel y observar este esquema de denominación.
En el ejemplo siguiente se utiliza el método MakeGenericType para crear un tipo construido a partir de la definición de tipo genérico para el tipo Dictionary. El tipo construido representa una colección Dictionary de objetos Test con claves de cadena.
Imports System
Imports System.Reflection
Imports System.Collections.Generic
Imports Microsoft.VisualBasic
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
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
*/
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
*/
Windows 98, Windows 2000 SP4, Windows Millennium, Windows Server 2003, Windows XP Media Center, Windows XP Professional x64, Windows XP SP2, Windows XP Starter Edition
.NET Framework no admite todas las versiones de cada plataforma. Para obtener una lista de las versiones admitidas, vea Requisitos del sistema.
.NET Framework
Compatible con: 2.0
.NET Compact Framework
Compatible con: 2.0