views:

84

answers:

4

How do I get the actual type of T in a generic List at run time using reflection?

A: 

I believe this is what you're searching for. It will get the generic parameters for your object, should they exist.

Type[] types = obj.GetType().GetGenericArguments();
Anthony Pegram
+2  A: 

You can use Type.GetGenericArguments to return the type T in a List<T>.

For example, this will return the Type for any List<T> passed as an argument:

Type GetListType(object list)
{
    Type type = list.GetType();
    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
        return type.GetGenericArguments()[0];
    else
        throw new ArgumentException("list is not a List<T>", "list");
}
Reed Copsey
Not really useful: You can only pass an object in there for which you already know the type at compile-time.
Timwi
@Timwi - I can think of a dozen places this is useful, just because you have a `T` at compile time, doesn't mean you know it (generic constraints for example). There there are a few ways to go about it, e.g. `ElementType` on an `IQueryable<T>`, but don't dismiss this as not useful.
Nick Craver
@Timwi: Although I put this just as a very simple usage scenario - it works fully from reflection, as well. The GetGenericArguments call is the main way, via reflection, to pull this out. Granted, in this case, I could just have returned typeof(T) and been done with it - but I don't know how the OP is getting the "List<T>" in the first place... That being said, doing reflection on generic arguments in a generic method like this can be useful in some situations...
Reed Copsey
@Nick, @Reed: Can you provide some example code (e.g. via pastebin.com) where it would actually be useful? The way I see it, wherever you write `GetGenericType(list)`, the type of `list` must at compile-time be `List<X>` with `X` known at compile-time, so no matter what `X` is, you can just as easily write `typeof(X)` instead.
Timwi
@Timwi: Does that make you happier? Now it's getting the full type via reflection... including the proper checks to see if it's a List<T> via IsGenericType + the TypeDefinition check...
Reed Copsey
Yes, now your answer is pretty much identical to mine ☺
Timwi
@Timwi: Except for the extra comment I added on yours ;)
Reed Copsey
A: 
typeof (T)

or

typeof (T).UnderlyingSystemType
Ivan Ferić
+4  A: 

It depends on what exactly you’re asking:

  • While writing code inside a generic type Blah<T>, how do I get the reflection type T?

    Answer: typeof(T)

  • I have an object which contains a List<T> for some type T. How do I retrieve the type T via reflection?

    Short answer: myList.GetType().GetGenericArguments()[0]

    Long answer:

    var objectType = myList.GetType();
    if (!objectType.IsGenericType() ||
        objectType.GetGenericTypeDefinition() != typeof(List<>))
    {
        throw new InvalidOperationException(
            "Object is not of type List<T> for any T");
    }
    var elementType = objectType.GetGenericArguments()[0];
    
Timwi
BTW - This will throw on GetGenericTypeDefinition() if "myList" is not a generic type... If you're going to put in the error checking, you should include a check for IsGenericType, too.
Reed Copsey
Good catch, thanks.
Timwi