Question

I am learning c# and trying to understand the "type oriented" aspects of it.

So the other day I needed to receive an System.Array object from a method. Then I tried to work with it's individual objects, so i tried to address it with an index. Compiler wouldn't let me, saying that System.Array object do not support indexing.

But isn't Array is the base class to all arrays (System.Array on msdn)? How is that int[] supports indexing and Array[] doesn't?

here is some code to demonstrate the problem:

int[] intArray = {1,2,3,4,5,6,7,8,9,10};
int t;
Array sysArray;       
Console.WriteLine("{0}", intArray.GetType().ToString()); // output: System.Int32[]
sysArray = Array.CreateInstance(typeof(int), 10);
Console.WriteLine("{0}", sysArray.GetType().ToString()); // output: System.Int32[]
sysArray = intArray; //compiles ok
//t = sysArray[4]; This line produces error Error 2 Cannot apply indexing with [] to an
// expression of type 'System.Array'
//t = intArray[4]; This line compiles ok

So what we have here is 2 objects, that seem to be of the same type. But one is implementing indexing and the other is not, how is it possible?


a reference to the replies

after reading your comments i think i got the sense of things. int[] is and array of objects. each of the objects is a struct of type int32. Array[] is an array of objects. each of the objects is a class of type Array. meaning : an array of arrays. as i can display in the following code:

Array[] sysArrayOfArray = new Array[SIZE_OF_THE_MOTHER_ARRAY];
sysArrayOfArray[0] = Array.CreateInstance(typeof(int),SIZE_OF_FIRST_CHILD_ARRAY);
sysArrayOfArray[1] = Array.CreateInstance(typeof(int),SIZE_OF_FIRST_SECOND_ARRAY);

and so on... so I understood why the way i tried to access the elements of sysArray was wrong. intArray -> 1 array of many ints sysArray -> 1 class (which grants access to many ints)

from the language's point of view sysArray is not an Array at all, it is only a reference to 1 object (of type System.Array)

(sorry for repeating a bit, but it really helps set things in my head)

thank you all for guiding in understanding that difference.

regarding the solutions.. that what i was looking for and worked for me best:

 Array sysArray = Array.CreateInstance(typeof(int),3);
 int[] intArray = new int[3];
 int one, ten, hundred;
 sysArray.SetValue(1, 0);
 sysArray.SetValue(10,1);
 sysArray.SetValue(100,2);
 intArray = (int[])sysArray;// works, but forces me to create a new reference
 one = ((int[])sysArray)[0];// works and is exactly what i was looking for...
 ten = ((int[])sysArray)[1];
 hundred = ((int[])sysArray)[2];    
Was it helpful?

Solution

Casting will take care of the difference:

    t = (sysArray as int[])[4];

You are seeing that both arrays are of type System.Int32[], because they are (which is why this cast works).

OTHER TIPS

int is declared as a struct in the BCL

public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<Int32>, Equatable<Int32> 

Whilst Array is declared like so:

public abstract class Array : ICloneable, IList, IStructuralComparable, IStructuralEquatable

So they are not actually the same.

If you do want to get items from Array using an indexer, I think you will need to do this:

int number = ((IList<int>)sysArray)[4];

The reason is due to how the indexer method is declared in Array:

Object IList.this[int index] { 
  get { return GetValue(index); }
  set { SetValue(value, index); } 
}

Since IList is declared in the signature, it means that you will need to cast sysArray into a IList<int> in order to access the indexer. If, instead, the indexer had been declared like this:

Object this[int index] {

then yes, you could do sysArray[0]; without any problems.

You have to look at the interfaces that each object implements. Array implements System.Collections.IList which provides an object indexer while int does not supply an IList implementation.

System.Array is an abstract base class. The microsoft documentation says it all...

Provides methods for creating, manipulating, searching, and sorting arrays, thereby
serving as the base class for all arrays in the common language runtime.

System.Array does not provide an implementation for the indexer.

What will work for you is this...

int[] sysArray = (int[])Array.CreateInstance(typeof(int), 10);

Assuming eventTypes are objects containing integer values (object[] eventTypes):

int[] eventTypeIDs = eventTypes.Select(Convert.ToInt32).ToArray();

You can read values of Array by using the GetValue function.

array.GetValue(1);
array.GetValue(1,2);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top