Подтвердить что ты не робот

Типы массивов с одинаковым типом элемента и рангом не равны

Очень просто:

var equal1 = typeof(object[]) == typeof(object).MakeArrayType();
var equal2 = typeof(object[]) == typeof(object).MakeArrayType(1);
var equal3 = typeof(object[,]) == typeof(object).MakeArrayType(2);

Предполагается, что все три должны быть истинными, но оказывается, что equal2 - false - что на самом деле не имеет смысла, учитывая, что первые два вызова MakeArrayType эквивалентны, а результирующие типы массивов то же самое.

Единственное различие, которое я могу заметить, заключается в том, что явное пропускание ранга типа массива как "1" дает a Type, чей Name is "Object[*]", тогда как опускание дает "Object[]".

Поэтому я подумал, что ранг object[] не 1 (хотя это явно есть!) - поэтому я сделал это:

var type1 = typeof(object[]);
var type2 = type1.GetElementType().MakeArrayType(type1.GetArrayRank());
var equal = type1 == type2; //false

Теперь типы определенно имеют одинаковый ранг, но не равны.

Этот сценарий больше похож на мой текущий сценарий, когда я пытаюсь построить ковариацию Array в Rezolver - поэтому я перекомпоную типы массивов, перейдя по базовым иерархиям и используя MakeArrayType с исходным рангом типа массива.

Итак - может ли кто-нибудь объяснить, почему два типа массива с одинаковым рангом не считаются равными?

Я понимаю, что, возможно, какой-то нюанс здесь отсутствует, и что есть обходные пути, которые я могу использовать, мне просто интересно, что происходит!

4b9b3361

Ответ 1

Документация объясняет разницу:

Общая среда исполнения языка делает различие между векторами (то есть одномерными массивами, которые всегда основаны на нуле) и многомерными массивами. Вектор, который всегда имеет только одно измерение, не совпадает с многомерным массивом, который имеет только одно измерение. Вы не можете использовать этот метод для перегрузки для создания векторного типа; если rank равно 1, этот метод перегрузки возвращает многомерный массив, который имеет одно измерение. Используйте метод MakeArrayType() для создания векторных типов.

В принципе, equal1 возвращает вектор, а equal2 возвращает многомерный массив, который имеет ранг 1.

В CLR два типа обрабатываются по-разному.

Интересно, что если вы создадите экземпляр типа, вы снова получите вектор:

var type = typeof(object).MakeArrayType(1);
// Create an instance with length 2
var array = Activator.CreateInstance(type, 2);
Console.WriteLine(array.GetType());            // System.Object[]
Console.WriteLine(type);                       // System.Object[*]

Array.CreateInstance показывает такое же поведение: если вы запрашиваете массив с нижней границей 0 и ранга 1, он всегда будет создавать вектор:

var array = Array.CreateInstance(typeof(object), new[] { 2 }, new[] { 0 });
Console.WriteLine(array.GetType());
object[] objArray = (object[]) array; // This is fine

Если вы измените значение 0 на любое ненулевое значение, оно создаст System.Object[*], и приведение не будет выполнено.