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

C#-获取通用列表的项目类型,c#,collections,generics,C#,Collections,Generics,获取通用列表包含的项目类型的最佳方法是什么?抓取集合中的第一个项并调用.GetType()很容易,但我不能总是确定集合中是否有项 希望这是有道理的 谢谢, 桑尼你可以用这个方法来达到这个目的 List<Foo> myList = ... Type myListElementType = myList.GetType().GetGenericArguments().Single(); List myList=。。。 类型myListElementType=myList.GetTyp

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

希望这是有道理的

谢谢,
桑尼

你可以用这个方法来达到这个目的

List<Foo> myList = ...

Type myListElementType = myList.GetType().GetGenericArguments().Single();
List myList=。。。
类型myListElementType=myList.GetType().GetGenericArguments().Single();

对于更稳健的方法:

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];
}
请注意,您甚至不需要
someList
参数。此方法只是一个示例,说明了如果您已经使用了泛型方法,如何使用
typeof
。仅当您无权访问
t
标记(列表存储在非泛型类型变量中,例如一个类型化的
IList
对象
,等等)时,才需要使用反射方法。

公共共享函数ListItemType(ListType作为System.Type)作为System.Type
如果不是ListType.IsGenericType,则
如果ListType.BaseType不是Nothing,也不是ListType.BaseType.IsGenericType,则
返回ListItemType(ListType.BaseType)
如果结束
其他的
返回ListType.GetGenericArguments.Single
如果结束
端函数

这是怎么回事,它全是静态的(例如,不需要实例)和快速的(无循环,不使用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());
        }
至于统计员:

    [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;
    }

以下是另一种适用于非泛型集合的方法:

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)));

带有
动态

void Foo(){
   Type type GetTypeT(data as dynamic);
}

private static Type GetTypeT<T>(IEnumerable<T> data)
{
    return typeof(T);
}
void Foo(){
类型GetTypeT(数据为动态);
}
私有静态类型GetTypeT(IEnumerable数据)
{
返回类型(T);
}
公共类型GetType(IEnumerable结果列表)
{
返回resultList.GetType().GetElementType();
}

这里有一个同样适用于派生类的解决方案

因为这门课:

  public class SubList : List<int>
  {   }

你对这种类型已经了解多少了?您可以提供一个示例上下文吗?如果
T
标记在范围内(例如,在接受
列表的方法中),您还可以使用
typeof(T)
。如果
列表
存储在
object
类型的变量中,您将不得不使用上述方法。您今天早些时候没有回答另一个几乎完全相同的问题吗?@LukeH:是的,闪电确实击中了两次:)@Lambert:我不是降价专家,但我选择了一个块,然后单击“代码示例”图标。我建议你点击答案框右上角的橙色“?”来获取更多关于这个东西如何工作的信息。谢谢!!那真的很有帮助!天哪,错误处理得很好。您可能还需要添加可本地化的错误文本。;)美好的一个小问题-传递给new ArgumentException的参数是错误的。在这里,您的方法接受每个接口的非泛型版本,但只有当它们实际实现泛型版本时,才会按预期工作。如果你要满足这些要求,你最好让这些方法直接接受接口的通用版本。虽然这个代码片段可以解决这个问题,但确实有助于提高你文章的质量。请记住,您将在将来回答读者的问题,这些人可能不知道您的代码建议的原因。还请尽量不要用解释性注释挤满您的代码,因为这会降低代码和解释的可读性!
// 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)));
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];
}
void Foo(){
   Type type GetTypeT(data as dynamic);
}

private static Type GetTypeT<T>(IEnumerable<T> data)
{
    return typeof(T);
}
    public Type GetType(IEnumerable<object> resultList)
    {
        return resultList.GetType().GetElementType();
    }
  public class SubList : List<int>
  {   }
public Type GetListItemType<T>(List<T> list)
{
  Type type = list.GetType();
  while (type != typeof(List<T>))
    type = type.BaseType;
  return type.GetGenericArguments().Single();
}


var list = new List<int>();
var subList = new SubList();
Console.WriteLine(GetListItemType(list)); // System.Int32
Console.WriteLine(GetListItemType(subList)); // System.Int32