casting system.array object to int[] string or other type's objects
Asked Answered
A

6

17

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];    
Antons answered 30/12, 2011 at 14:51 Comment(2)
Your question is not clear. An int is an object....So what you are doing makes little sense.Verbid
Good question. Shows that System.Array is not just an Array after all....Where is this world going MS?Pasadena
S
16

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).

Stumble answered 30/12, 2011 at 15:7 Comment(0)
C
5

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.

Calvaria answered 30/12, 2011 at 14:59 Comment(5)
Again, the OP is not asking why a single int can't be indexed. They are asking why a generic System.Array object can't be indexed.Inwards
When using int[] you're actually using a C# language construct i.e. arrays. That means there is in-built support for index accessing e.g. myarray[23];. In essence, your accessing an array of structs (int) The class Array is an object in itself, and so when using index access on it, you're not using the C# language, rather you're using whatever the indexer method is on that class i.e. Object IList.this[int index]. So in a nutshell, the index accessor methods for each type is totally different.Calvaria
I do not think arrays are a "C# language construct". Using square brackets for array element indexing is a language construct...the existence of arrays is a fundamental feature of the CLI. See ECMA-335:8.9.1 Array types. As for IList, it includes (as you note) the indexer this[int index]. So how can System.Array implement IList without implementing the required member this[int index]?Inwards
Hmmm, I can see where you're going with this. The issue is that Array has it's indexer implement via Object IList.this[int index]. If it was declared Object this[int index] then you could do sysArray[0] without any problems. But because IList is declared in the signature, that makes a difference, and causes us to have to cast sysArray in order to access it's indexer. I think the ultimate question is why bother with the Array class at all?Calvaria
thank you both, your example and discussion actually helped me understand what sysArray really was. @JasonEvansAntons
O
1

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.

Oil answered 30/12, 2011 at 15:0 Comment(1)
That's not what the OP is implying. The OP is asking why the abstract System.Array class does not allow element access using indexer syntax: It's the expression sysarray[4] that bombs.Inwards
C
1

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);
Claver answered 30/12, 2011 at 15:7 Comment(0)
G
1

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

int[] eventTypeIDs = eventTypes.Select(Convert.ToInt32).ToArray();
Gmt answered 26/6, 2013 at 20:43 Comment(0)
D
0

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

array.GetValue(1);
array.GetValue(1,2);
Divebomb answered 21/8, 2013 at 12:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.