【问题标题】:Unable to get a Span<Type> from all types in an assembly无法从程序集中的所有类型中获取 Span<Type>
【发布时间】:2021-01-04 14:20:05
【问题描述】:

我正在尝试获取程序集中的所有类型 (assembly.GetTypes()),并尝试从中获得一个跨度,而无需任何看起来像 assembly.GetTypes().AsSpan() 的堆分配。然而奇怪的是,这会引发以下错误:

System.ArrayTypeMismatchException: '试图以与数组不兼容的类型访问元素。'

这让我有点困惑,更让我困惑的是assembly.GetTypes().ToArray().AsSpan() 运行时没有任何问题,但这显然不是解决方案。

一个小提琴,它表明这可以在here找到。

【问题讨论】:

    标签: c# .net-core


    【解决方案1】:

    assembly.GetTypes() 返回一个RuntimeType[],但它使用数组类型协方差将其伪装成Type[]。根据Span constructor 的文档,如果T(在本例中为Type)与运行时数组类型(在本例中为RuntimeType)不匹配,则会引发ArrayTypeMismatchException

    另一方面,

    assembly.GetTypes().ToArray() 返回一个实际的Type[]:它将根据声明的类型T(即Type)创建一个全新数组,因此您会得到一个真正的 Type[] 数组并且没有不匹配 -- TType 并且您将真正的 Type[] 传递给 Span 构造函数。

    ReadOnlySpan&lt;T&gt; 没有这个约束,因为不可能将不兼容的Type 写入只读的RuntimeType[],所以你可以这样做:

    new ReadOnlySpan<Type>(assembly.GetTypes());
    

    【讨论】:

    • 而且 RuntimeType 是不公开的,所以将其转换回不必复制数组是不可能的(只是想找到一个不涉及复制数组的解决方案)
    • 我的意思是这绝对是有道理的,即使这确实有点让人头疼,因为无论我做什么,我都不能直接从这个数组创建一个跨度,对吧?
    • 这样的感觉应该记录在AsSpan方法中。
    • @Twenty 我已经用可能对您有用的替代方法更新了我的答案。如果您不打算向跨度写入任何内容,那么您可以使用不会抛出的ReadOnlySpan
    • @Jeff Oh 实际上比预期的要容易得多,幸运的是我没有修改数组,所以非常感谢!
    猜你喜欢
    • 2011-01-15
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 2019-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多