C# - Get the item type for a generic list

Solution 1:

You could use the Type.GetGenericArguments method for this purpose.

List<Foo> myList = ...

Type myListElementType = myList.GetType().GetGenericArguments().Single();

Solution 2:

For a more robust approach:

public static Type GetListType(object someList)
{
    if (someList == null)
        throw new ArgumentNullException("someList");

    var type = someList.GetType();

    if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(List<>))
        throw new ArgumentException("Type must be List<>, but was " + type.FullName, "someList");

    return type.GetGenericArguments()[0];
}

But if your variable is typed List<T> then you can just use typeof(T). For example:

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

Note that you don't really even need the someList parameter. This method is just an example for how you could use typeof if you are already in a generic method. You only need to use the reflection approach if you don't have access to the T token (the list is stored in a non-generic-typed variable, such as one typed IList, object, etc.).

Solution 3:

list.GetType().GetGenericArguments()[0]

Solution 4:

Here's another way which works for non-generic collections, too:

static Type GetItemType(Type collectionType)
{
    return collectionType.GetMethod("get_Item").ReturnType;
}

That is, get the return type of foo[x], where foo is of the specified type.

Examples:

// Generic type; prints System.Int32
Console.WriteLine(GetItemType(typeof(List<int>)));

// Non-generic type; prints System.String
Console.WriteLine(GetItemType(typeof(System.Collections.Specialized.StringCollection)));

The GetItemType method above has a couple issues, though:

  • It throws a NullReferenceException if the type has no indexing operator.

  • It throws an AmbiguousMatchException if the type has multiple overloads for the indexing operator (e.g. this[string] and this[int]).

Here is a more refined version:

public static Type GetItemType(this Type collectionType)
{
    var types =
        (from method in collectionType.GetMethods()
         where method.Name == "get_Item"
         select method.ReturnType
        ).Distinct().ToArray();
    if (types.Length == 0)
        return null;
    if (types.Length != 1)
        throw new Exception(string.Format("{0} has multiple item types", collectionType.FullName));
    return types[0];
}