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

时间:2010-12-15 16:51:47

标签: c# collections generics

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

希望这是有道理的。

谢谢,
桑尼

9 个答案:

答案 0 :(得分:69)

您可以使用Type.GetGenericArguments方法实现此目的。

List<Foo> myList = ...

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

答案 1 :(得分: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];
}

但如果您的变量是List<T>,那么您可以使用typeof(T)。例如:

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

请注意,您甚至不需要someList参数。如果您已经在泛型方法中,此方法只是如何使用typeof的示例。如果您无权访问T令牌,则只需使用反射方法(列表存储在非泛型类型变量中,例如一个类型IList,{{1等等。)。

答案 2 :(得分:5)

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

答案 3 :(得分:5)

这是另一种适用于非泛型集合的方式:

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

即,获取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)));

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

  • 如果类型没有索引操作符,则抛出NullReferenceException

  • 如果类型具有索引运算符的多个重载(例如AmbiguousMatchExceptionthis[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];
}

答案 4 :(得分:2)

这个怎么样,它全是静态的(例如没有实例需要),快速(没有循环,没有使用linq),而且很简单:)这些工作适用于集合:

    [System.Diagnostics.DebuggerHidden]
    public static Type GetIndexedType(this ICollection poICollection)
    {
        PropertyInfo oPropertyInfo = poICollection == null ? null : poICollection.GetType().GetProperty("Item");
        return oPropertyInfo == null ? null : oPropertyInfo.PropertyType;
    }

    [System.Diagnostics.DebuggerHidden]
    public static Type GetEnumeratedType(this ICollection poICollection)
    {
        PropertyInfo oPropertyInfo = poICollection == null ? null : poICollection.GetType().GetMethod("GetEnumerator").ReturnType.GetProperty("Current");
        return oPropertyInfo == null ? null : oPropertyInfo.PropertyType;
    }

一些简单的单元测试:

        [Test]
        public void GetIndexedType()
        {
            Assert.AreEqual(null, ((ICollection)null).GetIndexedType());
            Assert.AreEqual(typeof(int), (new List<int>()).GetIndexedType());
            Assert.AreEqual(typeof(bool), (new SortedList<string, bool>()).GetIndexedType());
        }

        [Test]
        public void GetEnumeratedType()
        {
            Assert.AreEqual(null, ((ICollection)null).GetEnumeratedType());
            Assert.AreEqual(typeof(int), (new List<int>()).GetEnumeratedType());
            Assert.AreEqual(typeof(KeyValuePair<string, bool>), (new SortedList<string, bool>()).GetEnumeratedType());
        }

请注意,有两种方法可以查看此内容,索引器可能会返回一种类型,枚举器可能会返回另一种类型。单元测试确实显示了两者。

玩得开心, 反

P.S。对于可枚举:

    [System.Diagnostics.DebuggerHidden]
    public static Type GetEnumeratedType(this System.Collections.IEnumerable poIEnumerable)
    {
        PropertyInfo oPropertyInfo = poIEnumerable == null ? null : poIEnumerable.GetType().GetMethod("GetEnumerator").ReturnType.GetProperty("Current");
        return oPropertyInfo == null ? null : oPropertyInfo.PropertyType;
    }

对于调查员:

    [System.Diagnostics.DebuggerHidden]
    public static Type GetEnumeratedType(this System.Collections.IEnumerator poIEnumerator)
    {
        PropertyInfo oPropertyInfo = poIEnumerator == null ? null : poIEnumerator.GetType().GetProperty("Current");
        return oPropertyInfo == null ? null : oPropertyInfo.PropertyType;
    }

答案 5 :(得分:1)

使用dynamic

的旧问题新方法
void Foo(){
   Type type GetTypeT(data as dynamic);
}

private static Type GetTypeT<T>(IEnumerable<T> data)
{
    return typeof(T);
}

答案 6 :(得分:1)

    public Type GetType(IEnumerable<object> resultList)
    {
        return resultList.GetType().GetElementType();
    }

答案 7 :(得分:0)

Public Shared Function ListItemType(ListType As System.Type) As System.Type

  If Not ListType.IsGenericType Then
    If ListType.BaseType IsNot Nothing AndAlso ListType.BaseType.IsGenericType Then
      Return ListItemType(ListType.BaseType)
    End If
  Else
    Return ListType.GetGenericArguments.Single
  End If
End Function

答案 8 :(得分:0)

这是一种也可用于派生类的解决方案。

因为这个课程:

ShowDialog

如果您致电: public class SubList : List<int> { }

它将引发 System.InvalidOperationException

通过这种方法,它适用于派生类:

subList.GetType().GetGenericArguments().Single()