801 votes

Comment obtenir le type de T à partir d'un membre d'une classe ou d'une méthode générique ?

Disons que j'ai un membre générique dans une classe ou une méthode, comme ceci :

public class Foo<T>
{
    public List<T> Bar { get; set; }

    public void Baz()
    {
        // get type of T
    }   
}

Lorsque j'instancie la classe, le T devient MyTypeObject1 La classe a donc une propriété de liste générique : List<MyTypeObject1> . Il en va de même pour une méthode générique dans une classe non générique :

public class Foo
{
    public void Bar<T>()
    {
        var baz = new List<T>();

        // get type of T
    }
}

Je voudrais savoir quel type d'objets la liste de ma classe contient. Donc quel type de T la propriété de la liste appelée Bar ou la variable locale baz contiennent ?

Je ne peux pas faire Bar[0].GetType() car la liste peut contenir zéro élément. Comment puis-je le faire ?

842voto

Tamas Czinege Points 49277

Si je comprends bien, votre liste a le même paramètre de type que la classe conteneur elle-même. Si c'est le cas, alors :

Type typeParameterType = typeof(T);

Si vous avez la chance d'avoir object comme paramètre de type, voir La réponse de Marc .

64 votes

J'aime la facilité de lecture typeof est. Si vous voulez connaître le type de T, utilisez simplement typeof(T) :)

2 votes

En fait, j'ai simplement utilisé typeof(Type) et cela fonctionne très bien.

3 votes

Vous ne pouvez pas utiliser typeof() avec un paramètre générique, cependant.

564voto

Marc Gravell Points 482669

(note : je suppose que tout ce que tu sais est object ou IList ou similaire, et que la liste pourrait être de n'importe quel type au moment de l'exécution)

Si vous savez que c'est un List<T> alors :

Type type = abc.GetType().GetGenericArguments()[0];

Une autre option consiste à examiner l'indexeur :

Type type = abc.GetType().GetProperty("Item").PropertyType;

Utilisation du nouveau TypeInfo :

using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];

3 votes

Type type = abc.GetType().GetGenericArguments()[0] ; ==> Index de tableau hors limites...

33 votes

@Daok : alors ce n'est pas une List<T>.

0 votes

Besoin de quelque chose pour BindingList ou List ou tout autre objet qui contient un <T>. Ce que je fais, c'est utiliser un BindingListView<T> personnalisé.

57voto

3dGrabber Points 761

Avec la méthode d'extension suivante, vous pouvez vous passer de la réflexion :

public static Type GetListType<T>(this List<T> _)
{
    return typeof(T);
}

Ou plus général :

public static Type GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return typeof(T);
}

Utilisation :

List<string>        list    = new List<string> { "a", "b", "c" };
IEnumerable<string> strings = list;
IEnumerable<object> objects = list;

Type listType    = list.GetListType();           // string
Type stringsType = strings.GetEnumeratedType();  // string
Type objectsType = objects.GetEnumeratedType();  // BEWARE: object

15 votes

Ceci n'est utile que si vous connaissez déjà le type de T au moment de la compilation. Dans ce cas, vous n'avez pas vraiment besoin de code.

2 votes

@recursive : C'est utile si vous travaillez avec une liste d'un type anonyme.

34voto

Rauhotz Points 3155

Essayez

list.GetType().GetGenericArguments()

7 votes

New List<int>().GetType().GetGenericArguments() retourne System.Type[1] ici avec System.Int32 comme entrée

1 votes

@Rauhotz le GetGenericArguments retourne un objet Array de Type dont vous devez ensuite extraire la position du type générique dont vous avez besoin. Par exemple Type<TKey, TValue> : vous devez GetGenericArguments()[0] pour obtenir TKey et GetGenericArguments()[1] pour obtenir TValue type

8voto

Ferenc Mucsi Points 61

Considérez ceci :

Je l'utilise pour exporter 20 listes dactylographiées de la même manière :

private void Generate<T>()
{
    T item = (T)Activator.CreateInstance(typeof(T));

    ((T)item as DemomigrItemList).Initialize();

    Type type = ((T)item as DemomigrItemList).AsEnumerable().FirstOrDefault().GetType();
    if (type == null) 
        return;
    if (type != typeof(account)) // Account is listitem in List<account>
    {
        ((T)item as DemomigrItemList).CreateCSV(type);
    }
}

1 votes

Cela ne fonctionne pas si T est une superclasse abstraite des objets réels ajoutés. Sans compter que new T(); ferait la même chose que (T)Activator.CreateInstance(typeof(T)); . Il faut ajouter where T : new() à la définition de la classe/fonction, mais si vous quiere pour fabriquer des objets, cela devrait être fait de toute façon.

0 votes

Aussi, vous appelez GetType sur un FirstOrDefault entraînant une exception potentielle de référence nulle. Si vous êtes sûr qu'il retournera au moins un élément, pourquoi ne pas utiliser First à la place ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X