Невозможно получить диапазон из всех типов в сборке

#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 О, на самом деле это намного проще, чем ожидалось, к счастью, я не изменяю массив, так что большое спасибо!