假设我在类或方法中有一个泛型成员,所以:
public class Foo{ public List Bar { get; set; } public void Baz() { // get type of T } }
当我实例化类时,T
变为MyTypeObject1
,所以类具有通用列表属性:List
.这同样适用于非泛型类中的泛型方法:
public class Foo { public void Bar() { var baz = new List (); // get type of T } }
我想知道,我的类列表包含什么类型的对象.所以调用的list属性Bar
或局部变量baz
包含什么类型的T
?
我做不到Bar[0].GetType()
,因为列表可能包含零元素.我该怎么做?
如果我理解正确,您的列表与容器类本身具有相同的类型参数.如果是这种情况,那么:
Type typeParameterType = typeof(T);
如果您处于object
作为类型参数的幸运情况,请参阅Marc的答案.
(注:我假设你知道object
或IList
或类似的,并且这个名单可以是任何类型的在运行时)
如果你知道它是a List
,那么:
Type type = abc.GetType().GetGenericArguments()[0];
另一种选择是查看索引器:
Type type = abc.GetType().GetProperty("Item").PropertyType;
使用新的TypeInfo:
using System.Reflection; // ... var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];
使用以下扩展方法,您可以在没有反射的情况下逃脱:
public static Type GetListType(this List _) { return typeof(T); }
或者更一般:
public static Type GetEnumeratedType(this IEnumerable _) { return typeof(T); }
用法:
Listlist = new List { "a", "b", "c" }; IEnumerable strings = list; IEnumerable
尝试
list.GetType().GetGenericArguments()
这对我有用.myList是一些未知的列表.
IEnumerable myEnum = myList as IEnumerable; Type entryType = myEnum.AsQueryable().ElementType;
如果您不需要整个Type变量并且只想检查类型,则可以轻松创建临时变量并使用is运算符.
T checkType = default(T); if (checkType is MyClass) {}
您可以将此一个用于通用列表的返回类型:
public string ListType(T value) { var valueType = value.GetType().GenericTypeArguments[0].FullName; return valueType; }
考虑一下:我使用它以相同的方式导出20个类型列表:
private void Generate() { T item = (T)Activator.CreateInstance(typeof(T)); ((T)item as DemomigrItemList).Initialize(); Type type = ((T)item as DemomigrItemList).AsEnumerable().FirstOrDefault().GetType(); if (type == null) return; if (type != typeof(account)) //account is listitem in List { ((T)item as DemomigrItemList).CreateCSV(type); } }
GetGenericArgument()
必须在实例的基本类型(其类是泛型类myClass
)上设置该方法.否则,它返回一个类型[0]
例:
Myclassinstance = new Myclass (); Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();
您可以使用以下方法从实现IEnumerable
public static Type GetCollectionItemType(Type collectionType) { var types = collectionType.GetInterfaces() .Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>)) .ToArray(); // Only support collections that implement IEnumerableonce. return types.Length == 1 ? types[0].GetGenericArguments()[0] : null; }
请注意,它不支持两次实现IEnumerable
public class WierdCustomType : IEnumerable, IEnumerable { ... }
我想如果您需要支持此类型,则可以返回一个类型数组。
另外,如果您经常这样做(例如循环执行),则可能还希望按集合类型缓存结果。
我使用此扩展方法来完成类似的操作:
public static string GetFriendlyTypeName(this Type t) { var typeName = t.Name.StripStartingWith("`"); var genericArgs = t.GetGenericArguments(); if (genericArgs.Length > 0) { typeName += "<"; foreach (var genericArg in genericArgs) { typeName += genericArg.GetFriendlyTypeName() + ", "; } typeName = typeName.TrimEnd(',', ' ') + ">"; } return typeName; } public static string StripStartingWith(this string s, string stripAfter) { if (s == null) { return null; } var indexOf = s.IndexOf(stripAfter, StringComparison.Ordinal); if (indexOf > -1) { return s.Substring(0, indexOf); } return s; }
您可以这样使用它:
[TestMethod] public void GetFriendlyTypeName_ShouldHandleReallyComplexTypes() { typeof(Dictionary>).GetFriendlyTypeName() .ShouldEqual("Dictionary >"); }
这并不是您要找的东西,但是对演示所涉及的技术很有帮助。