C# Language Détermination des arguments génériques des instances de types génériques


Exemple

Si vous avez une instance d'un type générique mais que, pour une raison quelconque, vous ne connaissez pas le type spécifique, vous souhaiterez peut-être déterminer les arguments génériques utilisés pour créer cette instance.

Disons que quelqu'un a créé une instance de List<T> comme ça et la passe à une méthode:

var myList = new List<int>();
ShowGenericArguments(myList);

ShowGenericArguments a cette signature:

public void ShowGenericArguments(object o)

au moment de la compilation, vous n'avez aucune idée des arguments génériques utilisés pour créer o . Reflection fournit de nombreuses méthodes pour inspecter les types génériques. Au début, nous pouvons déterminer si le type de o est un type générique du tout:

public void ShowGenericArguments(object o)
{
    if (o == null) return;

    Type t = o.GetType();
    if (!t.IsGenericType) return;
    ...

Type.IsGenericType renvoie true si le type est un type générique et false si ce n'est pas le cas.

Mais ce n'est pas tout ce que nous voulons savoir. List<> est lui-même un type générique. Mais nous voulons seulement examiner les instances de types génériques construits spécifiques. Un type générique construit est par exemple un List<int> qui possède un argument de type spécifique pour tous ses paramètres génériques.

La classe Type fournit deux propriétés supplémentaires, IsConstructedGenericType et IsGenericTypeDefinition , pour distinguer ces types génériques construits des définitions de type génériques:

typeof(List<>).IsGenericType // true
typeof(List<>).IsGenericTypeDefinition // true
typeof(List<>).IsConstructedGenericType// false

typeof(List<int>).IsGenericType // true
typeof(List<int>).IsGenericTypeDefinition // false
typeof(List<int>).IsConstructedGenericType// true

Pour énumérer les arguments génériques d'une instance, nous pouvons utiliser la méthode GetGenericArguments() qui renvoie un tableau Type contenant les arguments de type générique:

public void ShowGenericArguments(object o)
{
    if (o == null) return;   
    Type t = o.GetType();
    if (!t.IsConstructedGenericType) return;

    foreach(Type genericTypeArgument in t.GetGenericArguments())
        Console.WriteLine(genericTypeArgument.Name);
}

L'appel du dessus ( ShowGenericArguments(myList) ) aboutit à cette sortie:

Int32