无法从程序集中的所有类型中获取 Span<Type>
Posted
技术标签:
【中文标题】无法从程序集中的所有类型中获取 Span<Type>【英文标题】:Unable to get a Span<Type> from all types in an assembly 【发布时间】:2021-01-04 14:20:05 【问题描述】:我正在尝试获取程序集中的所有类型 (assembly.GetTypes()
),并尝试从中获得一个跨度,而无需任何看起来像 assembly.GetTypes().AsSpan()
的堆分配。然而奇怪的是,这会引发以下错误:
System.ArrayTypeMismatchException: '试图以与数组不兼容的类型访问元素。'
这让我有点困惑,更让我困惑的是assembly.GetTypes().ToArray().AsSpan()
运行时没有任何问题,但这显然不是解决方案。
一个小提琴,它表明这可以在here找到。
【问题讨论】:
【参考方案1】:assembly.GetTypes()
返回一个RuntimeType[]
,但它使用数组类型协方差将其伪装成Type[]
。根据Span
constructor 的文档,如果T
(在本例中为Type
)与运行时数组类型(在本例中为RuntimeType
)不匹配,则会引发ArrayTypeMismatchException
。
assembly.GetTypes().ToArray()
返回一个实际的Type[]
:它将根据声明的类型T
(即Type
)创建一个全新数组,因此您会得到一个真正的 Type[]
数组并且没有不匹配 -- T
是 Type
并且您将真正的 Type[]
传递给 Span
构造函数。
ReadOnlySpan<T>
没有这个约束,因为不可能将不兼容的Type
写入只读的RuntimeType[]
,所以你可以这样做:
new ReadOnlySpan<Type>(assembly.GetTypes());
【讨论】:
而且 RuntimeType 是不公开的,所以将其转换回不必复制数组是不可能的(只是想找到一个不涉及复制数组的解决方案) 我的意思是这绝对是有道理的,即使这确实有点让人头疼,因为无论我做什么,我都不能直接从这个数组创建一个跨度,对吧? 这样的感觉应该记录在AsSpan
方法中。
@Twenty 我已经用可能对您有用的替代方法更新了我的答案。如果您不打算向跨度写入任何内容,那么您可以使用不会抛出的ReadOnlySpan
。
@Jeff Oh 实际上比预期的要容易得多,幸运的是我没有修改数组,所以非常感谢!以上是关于无法从程序集中的所有类型中获取 Span<Type>的主要内容,如果未能解决你的问题,请参考以下文章
Span<T> 和朋友不在 .NET Native UWP 应用程序中工作
为啥我无法从与设置文件相同的项目/程序集中为设置选择自定义类型?