C# - 获取通用列表的项类型

Son*_*Boy 40 c# generics collections

获取通用列表包含的项类型的最佳方法是什么?抓取集合中的第一个项目并调用.GetType()很容易,但我不能总是确定集合中会有一个项目.

希望有道理.

谢谢,
桑尼

Ani*_*Ani 78

您可以将此 Type.GetGenericArguments方法用于此目的.

List<Foo> myList = ...

Type myListElementType = myList.GetType().GetGenericArguments().Single();
Run Code Online (Sandbox Code Playgroud)

  • 如果`T`标记在范围内(比如,在接受`List <T>`的方法中),你也可以使用`typeof(T)`.如果`List <T>`存储在`object`类型的变量中,则必须使用上述方法. (2认同)

cdh*_*wie 8

对于更强大的方法:

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("someList", "Type must be List<>, but was " + type.FullName);

    return type.GetGenericArguments()[0];
}
Run Code Online (Sandbox Code Playgroud)

但如果输入你的变量,List<T>那么你可以使用typeof(T).例如:

public static Type GetListType<T>(List<T> someList)
{
    return typeof(T);
}
Run Code Online (Sandbox Code Playgroud)

请注意,您甚至不需要someList参数.typeof如果您已经在泛型方法中,此方法只是您可以使用的示例.你只需要使用反射的方法,如果你没有访问T令牌(该列表存储在非泛型类型的变量,如一个类型化的IList,object等等).


Meh*_*dad 6

list.GetType().GetGenericArguments()[0]
Run Code Online (Sandbox Code Playgroud)


Joe*_*ams 5

这也是适用于非通用集合的另一种方式:

static Type GetItemType(Type collectionType)
{
    return collectionType.GetMethod("get_Item").ReturnType;
}
Run Code Online (Sandbox Code Playgroud)

也就是说,获取的返回类型foo[x],其中foo是指定类型的返回类型。

例子:

// 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)));
Run Code Online (Sandbox Code Playgroud)

GetItemType上面的方法有两个问题:

  • NullReferenceException如果类型没有索引运算符,则抛出。

  • AmbiguousMatchException如果该类型对于索引运算符(例如this[string]this[int])具有多个重载,则抛出。

这是一个更完善的版本:

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];
}
Run Code Online (Sandbox Code Playgroud)