假设有一个System.String[]
类型的对象。我可以查询该类型对象以确定它是否为数组
Type t1 = typeof(System.String[]);
bool isAnArray = t1.IsArray; // should be true
但是,我如何从t1获取数组项的类型对象
Type t2 = ....; // should be typeof(System.String)
假设有一个System.String[]
类型的对象。我可以查询该类型对象以确定它是否为数组
Type t1 = typeof(System.String[]);
bool isAnArray = t1.IsArray; // should be true
但是,我如何从t1获取数组项的类型对象
Type t2 = ....; // should be typeof(System.String)
Type.GetElementType
来实现此目的。Type t2 = t1.GetElementType();
[Returns] 返回当前数组、指针或引用类型所包含或引用的对象类型,如果当前 Type 不是数组或指针,也不是通过引用传递,或者表示泛型类型或泛型方法中的类型参数,则返回 null。
感谢 @psaxton 的评论指出 Array 和其他集合之间的区别。作为扩展方法:
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
typeof(IEnumerable).IsAssinableFrom(type)
是否成立。 - Shimmy WeitzhandlerIObservable<T>
或其他类型,我会将该方法类型更改为GetGenericType
。 - Shimmy Weitzhandler感谢@drzaus提供的优秀的答案,但它可以被压缩成一行代码(同时检查null
和IEnumerable
类型):
public static Type GetEnumeratedType(this Type type) =>
type?.GetElementType()
?? typeof(IEnumerable).IsAssignableFrom(type)
? type.GenericTypeArguments.FirstOrDefault()
: null;
为了避免异常,我添加了null
检查器,也许我不应该这样做(可以删除Null Conditional Operators)。
还添加了一个过滤器,使函数仅适用于集合,而不是任何通用类型。
请记住,这也可能会被实现的子类欺骗,从而改变集合的主题,并且实现者决定将集合的通用类型参数移到后面的位置。
C#8和可空性的转换答案:
public static Type GetEnumeratedType(this Type type) =>
((type?.GetElementType() ?? (typeof(IEnumerable).IsAssignableFrom(type)
? type.GenericTypeArguments.FirstOrDefault()
: null))!;
Array
类返回null
。”因此它可能只适用于T[]
形式。但在我使用Array.CreateInstance()
生成的Array
上测试时似乎没问题... - Mr. Ree