Type.MakeGenericType(Type[]) Méthode

Définition

Substitue les éléments d'un tableau de types aux paramètres de type de la définition du type générique actuel et retourne un objet Type qui représente le type construit résultant.

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

Paramètres

typeArguments
Type[]

Tableau de types à remplacer pour les paramètres de type du type générique actuel.

Retours

Type

Type représentant le type construit formé en substituant les éléments de typeArguments pour les paramètres de type du type générique actuel.

Exceptions

Le type actuel ne représente pas une définition de type générique. Autrement dit, IsGenericTypeDefinition retourne false.

typeArguments a la valeur null.

-ou- Tout élément de typeArguments est null.

Le nombre d’éléments de typeArguments n’est pas le même que le nombre de paramètres de type de la définition de type générique actuelle.

  • ou - Un élément de typeArguments ne répond pas aux contraintes spécifiées pour le paramètre de type correspondant du type générique actuel.

  • ou - typeArguments contient un élément qui est un type pointeur (IsPointer retourne true), un type by-ref (IsByRef retourne true) ou Void.

La méthode appelée n’est pas prise en charge dans la classe de base. Les classes dérivées doivent fournir une implémentation.

Exemples

L’exemple suivant utilise la MakeGenericType méthode pour créer un type construit à partir de la définition de type générique pour le Dictionary<TKey,TValue> type. Le type construit représente un Dictionary<TKey,TValue> objet avec des clés de Test chaîne.

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
 */
open System
open System.Collections.Generic

type Test() = class end

let displayTypeInfo (t: Type) =
    printfn $"\r\n{t}"

    printfn $"\tIs this a generic type definition? {t.IsGenericTypeDefinition}" 

    printfn $"\tIs it a generic type? {t.IsGenericType}"

    let typeArguments = t.GetGenericArguments()
    printfn $"\tList type arguments ({typeArguments.Length}):"
    for tParam in typeArguments do
        printfn $"\t\t{tParam}"

printfn "\r\n--- Create a constructed type from the generic Dictionary type."

// Create a type object representing the generic Dictionary 
// type, by calling .GetGenericTypeDefinition().
let generic = typeof<Dictionary<_,_>>.GetGenericTypeDefinition()
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.
let typeArgs = [| typeof<string>; typeof<Test> |]

// Create a Type object representing the constructed generic type.
let constructed = generic.MakeGenericType typeArgs
displayTypeInfo constructed

(* 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
 *)
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

Remarques

La MakeGenericType méthode vous permet d’écrire du code qui affecte des types spécifiques aux paramètres de type d’une définition de type générique, créant ainsi un Type objet qui représente un type construit particulier. Vous pouvez utiliser cet Type objet pour créer des instances d’exécution du type construit.

Les types construits avec MakeGenericType peuvent être ouverts, c’est-à-dire que certains de leurs arguments de type peuvent être des paramètres de type englobant des méthodes ou des types génériques. Vous pouvez utiliser ces types construits ouverts lorsque vous émettez des assemblys dynamiques. Par exemple, considérez les classes Base et Derived dans le code suivant.

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> { }
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

Pour générer Derived dans un assembly dynamique, il est nécessaire de construire son type de base. Pour ce faire, appelez la MakeGenericType méthode sur un Type objet représentant la classe Base, en utilisant les arguments Int32 de type générique et le paramètre V de type de Derived. Étant donné que les types et les paramètres de type générique sont tous deux représentés par Type des objets, un tableau contenant les deux peut être passé à la MakeGenericType méthode.

Notes

Un type construit tel qu’il Base<int, V> est utile lors de l’émission de code, mais vous ne pouvez pas appeler la MakeGenericType méthode sur ce type, car il ne s’agit pas d’une définition de type générique. Pour créer un type construit fermé qui peut être instancié, appelez d’abord la GetGenericTypeDefinition méthode pour obtenir un Type objet représentant la définition de type générique, puis appelez MakeGenericType avec les arguments de type souhaités.

L’objet Type retourné par MakeGenericType est le même que celui Type obtenu en appelant la GetType méthode du type construit résultant, ou la GetType méthode d’un type construit créé à partir de la même définition de type générique à l’aide des mêmes arguments de type.

Notes

Un tableau de types génériques n’est pas lui-même un type générique. Vous ne pouvez pas appeler MakeGenericType un type de tableau tel que C<T>[] (Dim ac() As C(Of T) dans Visual Basic). Pour construire un type générique fermé à partir de C<T>[], appelez GetElementType pour obtenir la définition C<T>de type générique ; appelez MakeGenericType la définition de type générique pour créer le type construit ; puis appelez la MakeArrayType méthode sur le type construit pour créer le type de tableau. Il en va de même pour les types et ref types de pointeur (ByRefdans Visual Basic).

Pour obtenir la liste des conditions indifférentes pour les termes utilisés dans la réflexion générique, consultez les notes sur la propriété IsGenericType.

Types imbriqués

Si un type générique est défini à l’aide de C#, C++ ou Visual Basic, ses types imbriqués sont tous génériques. Cela est vrai même si les types imbriqués n’ont pas de paramètres de type propres, car les trois langages incluent les paramètres de type des types englobants dans les listes de paramètres de type des types imbriqués. Tenez compte des classes suivantes :

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 liste des paramètres de type de la classe Inner imbriquée a deux paramètres de type et T U, le premier étant le paramètre de type de sa classe englobante. De même, la liste des paramètres de type de la classe Innermost1 imbriquée a trois paramètres de type, Tet U, avec T et V``U provenant de ses classes englobantes. La classe Innermost2 imbriquée a deux paramètres de type etU``T, qui proviennent de ses classes englobantes.

Si la liste de paramètres du type englobant a plusieurs paramètres de type, tous les paramètres de type dans l’ordre sont inclus dans la liste des paramètres de type du type imbriqué.

Pour construire un type générique à partir de la définition de type générique pour un type imbriqué, appelez la méthode avec le MakeGenericType tableau formé en concaténant les tableaux d’arguments de type de tous les types englobants, en commençant par le type générique le plus externe et en se terminant par le tableau d’arguments de type du type imbriqué lui-même, s’il a des paramètres de type propres. Pour créer une instance de Innermost1, appelez la MakeGenericType méthode avec un tableau contenant trois types, à affecter à T, U et V. Pour créer une instance de Innermost2, appelez la MakeGenericType méthode avec un tableau contenant deux types, à affecter à T et U.

Les langages propagent les paramètres de type des types englobants de cette manière afin de pouvoir utiliser les paramètres de type d’un type englobant pour définir des champs de types imbriqués. Sinon, les paramètres de type ne se trouvent pas dans l’étendue dans les corps des types imbriqués. Il est possible de définir des types imbriqués sans propager les paramètres de type des types englobants, en émettant du code dans des assemblys dynamiques ou à l’aide de l'Ilasm.exe (assembleur IL). Considérez le code suivant pour l’assembleur MSIL :

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

Dans cet exemple, il n’est pas possible de définir un champ de type T ou U de classe Innermost, car ces paramètres de type ne sont pas dans l’étendue. Le code assembleur suivant définit les classes imbriquées qui se comportent comme elles le feraient si elles sont définies en C++, Visual Basic et C# :

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

Vous pouvez utiliser le Ildasm.exe (désassembleur IL) pour examiner les classes imbriquées définies dans les langages de haut niveau et observer ce schéma d’affectation de noms.

S’applique à

Voir aussi