如何从.net中的数组types获取数组项types
说我有一个System.String[]
types的对象。 我可以查询types对象,以确定它是否是一个数组
Type t1 = typeof(System.String[]); bool isAnArray = t1.IsArray; // should be true
但是,我如何从t1获取数组项的types对象
Type t2 = ....; // should be typeof(System.String)
您可以使用实例方法Type.GetElementType
来达到此目的。
Type t2 = t1.GetElementType();
[返回]由当前数组,指针或引用types包含或引用的对象的types,如果当前的Type不是数组或指针,或者不是通过引用传递,或者表示genericstypes,则返回null或genericstypes或generics方法的定义中的types参数。
感谢@psaxton 评论指出了数组和其他集合之间的区别。 作为扩展方法:
public static class TypeHelperExtensions { /// <summary> /// If the given <paramref name="type"/> is an array or some other collection /// comprised of 0 or more instances of a "subtype", get that type /// </summary> /// <param name="type">the source type</param> /// <returns></returns> public static Type GetEnumeratedType(this Type type) { // provided by Array var elType = type.GetElementType(); if (null != elType) return elType; // otherwise provided by collection var elTypes = type.GetGenericArguments(); if (elTypes.Length > 0) return elTypes[0]; // otherwise is not an 'enumerated' type return null; } }
用法:
typeof(Foo).GetEnumeratedType(); // null typeof(Foo[]).GetEnumeratedType(); // Foo typeof(List<Foo>).GetEnumeratedType(); // Foo typeof(ICollection<Foo>).GetEnumeratedType(); // Foo typeof(IEnumerable<Foo>).GetEnumeratedType(); // Foo // some other oddities typeof(HashSet<Foo>).GetEnumeratedType(); // Foo typeof(Queue<Foo>).GetEnumeratedType(); // Foo typeof(Stack<Foo>).GetEnumeratedType(); // Foo typeof(Dictionary<int, Foo>).GetEnumeratedType(); // int typeof(Dictionary<Foo, int>).GetEnumeratedType(); // Foo, seems to work against key
感谢@drzaus提供了很好的答案 ,但它可以压缩到一个oneliner(加上检查null
和IEnumerable
types):
public static Type GetEnumeratedType(this Type type) => type?.GetElementType() ?? typeof(IEnumerable).IsAssignableFrom(type) ? type.GenericTypeArguments.FirstOrDefault() : null;
添加null
检查器,以避免exception,也许我不应该(随时删除空条件运算符 )。 还添加了一个filter,因此该函数只能在集合上工作,而不是任何genericstypes。
并且要记住,这也可能被实现的子类所迷惑,这些子类会改变集合的主题,实现者决定将集合的genericstypes的参数移到后面的位置。