如何从 .net 中的数组类型获取数组项类型

Posted

技术标签:

【中文标题】如何从 .net 中的数组类型获取数组项类型【英文标题】:How do I get the Array Item Type from Array Type in .net 【发布时间】:2011-05-07 00:02:26 【问题描述】:

假设我有一个System.String[] 类型的对象。我可以查询类型对象以确定它是否是一个数组

Type t1 = typeof(System.String[]);
bool isAnArray = t1.IsArray; // should be true

但是如何从 t1 获取数组项的类型对象

Type t2 = ....; // should be typeof(System.String)

【问题讨论】:

【参考方案1】:

您可以为此使用实例方法Type.GetElementType

Type t2 = t1.GetElementType();

[返回] 当前数组、指针或引用类型包含或引用的对象的类型,如果当前 Type 不是数组或指针,或者不是通过引用传递,或者表示一个泛型类型或泛型方法定义中的泛型类型或类型参数。

【讨论】:

Chrrrrrrrrrrrrrrrrrr 兄弟!谢谢一百万。 这适用于最初质疑的数组。作为参考,包含类型的集合可以作为 type.GetGenericArguments()[0] 访问 链接中的备注说“此方法为 Array 类返回 null。”所以它可能只适用于T[] 表单。但在我对Array.CreateInstance() 生成的Array 的测试中似乎还不错...【参考方案2】:

感谢@psaxton comment 指出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

【讨论】:

我确实在这里看到了一个小问题,即具有非 Colleciton 或数组的泛型的类呢。我将 if (type.IsArray || type.FullName.StartsWith("System.Collections")) 添加到等式中。 @André 有什么例子?你的意思是自定义类?因为真的,如果它是一个枚举类型,它应该(?)从IEnumerable继承;也许我对“集合”的使用应该是“可枚举的”? @André 不比较类型名称的字符串,而是检查 typeof(IEnumerable).IsAssinableFrom(type) @drzaus 他的意思是,如果我们检查一个不一定是IEnumerable 的泛型类型,例如IObservable&lt;T&gt;,或者其他什么。我会将方法类型更改为GetGenericType【参考方案3】:

感谢@drzaus 提供了很好的answer,但它可以被压缩成一个单行(加上检查nulls 和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))!;

【讨论】:

发生了一些变化,逐字复制此代码我收到此错误:“操作员'??'不能应用于“类型”和“布尔”类型的操作数”。 (.Net Core C#8)

以上是关于如何从 .net 中的数组类型获取数组项类型的主要内容,如果未能解决你的问题,请参考以下文章

如何从node.js中的二维数组中获取随机项[重复]

如何从 Java 中的未排序数组中快速获取前 N 个出现项?

从 pyspark 中的数据框数组类型列中获取“名称”元素

如何在android studio中从这种类型的json数组中获取价值?

如何获取每个数组项并插入 SQL 数据库?

labview如何获取簇数组中的数据名称、类型和数据值