Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array types with same element type & rank not equal

Very simple:

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

The assumption is that all three should be true, but it turns out that equal2 is false - which doesn't really make sense given that the first two MakeArrayType calls are equivalent and the resulting array types are the same.

The only difference I can actually discern is that explicitly passing the rank of the array type as '1' yields a Type whose Name is "Object[*]" whereas omitting it yields "Object[]".

So I thought, perhaps the rank of object[] isn't 1 (even though it clearly is!) - so I did this:

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

The types now definitely have the same rank, but are not equal.

This scenario is more like my current scenario as I try to build Array covariance into Rezolver - so I'm recomposing array types by walking base hierarchies and using MakeArrayType with the original array type's rank.

So - can anyone explain why two array types with identical rank are not considered equal?

I realise there's likely some nuance I'm missing here, and that there are workarounds I can use, I'm just curious as to what's going on!

like image 255
Andras Zoltan Avatar asked Aug 15 '17 13:08

Andras Zoltan


People also ask

Does array contain same datatype?

An array is a homogeneous data structure (elements have same data type) that stores a sequence of consecutively numbered objects--allocated in contiguous memory. Each object of the array can be accessed by using its number (i.e., index). When you declare an array, you set its size.

Can two elements of the same array be of different types?

No, we cannot store multiple datatype in an Array, we can store similar datatype only in an Array.

What are the 3 types of arrays?

There are three different kinds of arrays: indexed arrays, multidimensional arrays, and associative arrays.

Can you store elements of different data types in an array?

Yes we can store different/mixed types in a single array by using following two methods: Method 1: using Object array because all types in . net inherit from object type Ex: object[] array=new object[2];array[0]=102;array[1]="csharp";Method 2: Alternatively we can use ArrayList class present in System.

What data types can be used for array elements?

The data type of the array. This is also known as the element type. Supported data types are: BINARY, BIT, CHAR, VARCHAR, DATE, DECIMAL, DOUBLE PRECISION, FLOAT, INTEGER, NUMERIC, REAL, SMALLINT, TIME, TIMESTAMP, TIMESTAMP_TZ, TINYINT, and VARBINARY .

Can the index type of an array be any data type?

where Index is an ordinal type and Element is any type other than an open array type. The values of type T are arrays whose element type is Element and whose length is the number of elements of the type Index.


1 Answers

The documentation explains the difference:

The common language runtime makes a distinction between vectors (that is, one-dimensional arrays that are always zero-based) and multidimensional arrays. A vector, which always has only one dimension, is not the same as a multidimensional array that happens to have only one dimension. You cannot use this method overload to create a vector type; if rank is 1, this method overload returns a multidimensional array type that happens to have one dimension. Use the MakeArrayType() method overload to create vector types.

So basically, equal1 returns a vector, and equal2 returns a multidimensional array that happens to have a rank of 1.

The two types are treated very differently in the CLR.

Interestingly, if you create an instance of the type, you end up with a vector again:

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 shows the same behaviour: if you ask for an array with a lower bound of 0 and rank 1, it will always create a vector:

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

If you change the 0 to any non-zero value, it will create a System.Object[*] and the cast will fail.

like image 200
Jon Skeet Avatar answered Nov 11 '22 02:11

Jon Skeet