如何获取泛型列表中包含的项的类型?可以很容易地获取集合中的第一项并调用 .GetType(),但我不能保证集合中一定有项。
希望这样说得清楚。
谢谢,
Sonny
如何获取泛型列表中包含的项的类型?可以很容易地获取集合中的第一项并调用 .GetType(),但我不能保证集合中一定有项。
希望这样说得清楚。
谢谢,
Sonny
Type.GetGenericArguments
方法来实现此目的。List<Foo> myList = ...
Type myListElementType = myList.GetType().GetGenericArguments().Single();
T
标记处于作用域内(比如在一个接受List<T>
的方法中),你也可以使用typeof(T)
。如果List<T>
存储在类型为object
的变量中,则必须使用上述方法。 - cdhowie如果需要更加可靠的方法:
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];
}
但如果您的变量类型为 List<T>
,那么您可以使用 typeof(T)
。例如:
public static Type GetListType<T>(List<T> someList)
{
return typeof(T);
}
someList
参数。这个方法只是一个示例,展示了如果您已经在一个通用方法中,如何使用typeof
。如果您可以访问T
标记(列表存储在非泛型类型的变量中,例如IList
,object
等),则只需要使用反射方法。list.GetType().GetGenericArguments()[0]
这里有另一种方法,适用于非泛型集合:
static Type GetItemType(Type collectionType)
{
return collectionType.GetMethod("get_Item").ReturnType;
}
也就是说,获取指定类型的foo[x]
的返回类型。
例如:
// 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
异常。
如果类型对索引运算符有多个重载(例如this[string]
和this[int]
),它会抛出AmbiguousMatchException
异常。
这里是一个更加精细的版本:
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];
}
public Type GetType(IEnumerable<object> resultList)
{
return resultList.GetType().GetElementType();
}
这个东西很简单,全部都是静态的(例如不需要实例化),而且非常快(没有循环,不使用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.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;
}
旧问题新方法,使用 dynamic
void Foo(){
Type type GetTypeT(data as dynamic);
}
private static Type GetTypeT<T>(IEnumerable<T> data)
{
return typeof(T);
}
public class SubList : List<int>
{ }
subList.GetType().GetGenericArguments().Single()
会抛出一个System.InvalidOperationException
使用这种方法可以适用于派生类: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
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