#c# #.net-core
#c# #.net-core
Вопрос:
Я пытаюсь получить все типы в assembly ( assembly.GetTypes()
), и я пытаюсь получить span из этого без какого-либо выделения кучи, которое выглядело бы так assembly.GetTypes().AsSpan()
. Однако странно то, что это выдает следующую ошибку:
Система.ArrayTypeMismatchException: «Попытка получить доступ к элементу как к типу, несовместимому с массивом».
Что меня немного смутило, что сделало его еще более запутанным, так это то, что assembly.GetTypes().ToArray().AsSpan()
он работает без каких-либо проблем, но это, очевидно, не решение.
Скрипку, которая показывает это, можно найти прямо здесь.
Ответ №1:
assembly.GetTypes()
возвращает a RuntimeType[]
, но использует ковариацию типа массива, чтобы замаскировать его как a Type[]
. Согласно документации для Span
конструктора, ArrayTypeMismatchException
выбрасывается, если T
(что в данном случае есть Type
) не соответствует типу массива времени выполнения (который в данном случае есть RuntimeType
).
assembly.GetTypes().ToArray()
с другой стороны, возвращает значение actual Type[]
: оно создаст совершенно новый массив на основе объявленного типа T
, то есть Type
, таким образом, вы получаете true Type[]
array и нет несоответствия — T
is Type
, и вы передаете true Type[]
Span
конструктору.
ReadOnlySpan<T>
не имеет этого ограничения, поскольку невозможно записать несовместимое Type
только для чтения RuntimeType[]
, поэтому вы можете сделать это:
new ReadOnlySpan<Type>(assembly.GetTypes());
Комментарии:
1. И RuntimeType не является общедоступным, поэтому его возврат, чтобы не копировать массив, невозможен (просто пытаюсь найти решение, не связанное с копированием массива)
2. Я имею в виду, что это вызывающе имеет смысл, даже если это действительно немного заноза в заднице, поскольку, что бы я ни делал, я не мог напрямую создать span из этого массива, да?
3. Похоже, это должно быть задокументировано в
AsSpan
методе.4. @Twenty Я обновил свой ответ альтернативой, которая может сработать для вас. Если вы не собираетесь ничего записывать в span, то вы можете использовать a
ReadOnlySpan
, который не будет выдавать.5. @Jeff О, на самом деле это намного проще, чем ожидалось, к счастью, я не изменяю массив, так что большое спасибо!