# [.net] Assigning values to Array

This topic is 4422 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I want to do something like this:
foreach(Element e in someArray)
e = new e(...);


However, this gives me an error because you can't assign to a variable you are foreach'ing over. The reason I can't use the standard for-loops is because I don't know the dimensions or the rank of the array. Ultimately, what I want this for is to make an array of the same dimensions as the one I already have, but replace all the elements with element.Name (the array consists of elements of type IRecordable, which has a Name property). Maybe there's already a library function that does this? I couldn't find one. Thank you.

##### Share on other sites
Quote:
 The reason I can't use the standard for-loops is because I don't know the dimensions or the rank of the array

How is this possible? Arrays have "Length" and "Rank" properties..

##### Share on other sites
As the AP mentioned.
for(int i = 0; i < arr.Length; ++i) {  arr = blah;}

##### Share on other sites
Right, but it could be something like...

IRecordable[][,,][][,][,,,,,,,,]

I mean I guess it's possible, but is there an easier way of doing it?

Edit: Another problem is outlined in my other post on this forum about te Array's rank. Basically, I can find out the number of commas, but not brackets (so to speak), as that is what Array.Rank returns.

##### Share on other sites
I see what you mean. Not only do you have a multidimensional array, the elements within that array are themselves multidimensional arrays. So you have two problems: You need to initialize each array-of-arrays with nested arrays until there is no longer any nesting, at which point you need to initialize the array with new reference types.

Are you writing a generic container class?

void InitializeArray(Array array){  int[] indices = new int[array.Rank];  for (int r=0; r<array.Rank; ++r)    indices[r] = array.GetLength(r);    while (indexes[0] >= 0)  {    // use reflection to create an instance of array.GetType().GetElementType()    // but I can't quickly find out how I did this before.    array.SetValue(instance, indices);        if (array.GetType().GetElementType().GetArrayRank() > 0)    {      InitializeArray(instance as Array);    }        // adjust the multidimensional indices.    for (int r=array.Rank-1; r>=0; --r)    {      if (--indices[r] != 0)        break;    }  }}

Array.GetType().GetElementType() returns the inner array's type for each level of nesting.

Array.Rank obviously returns the rank, like everyone reading this thread knows by now.

Array.GetLength(int rank) returns the length of a particular rank in a multidimensional array.

The ultimate trick is to be able to create the nested array instances. You have to use reflection to do this. I forgot what the "create instance given a System.Type" function is, but I'm sure someone else will know.

##### Share on other sites
Thanks. That really helps. However, the problem is not initializing the array. The thing is, the array I'm creating will be the same exact dimensions as the old one (I'm basically replacing someClassInstance with someClassInstance.someMember). So I can clone the original array (since Arrays are not generic and have no specific type). Some the array is initialized fine, I just have to map the elements correctly. But thanks anyway, I'll give it another go, but I'd appreciate more responses.

##### Share on other sites
I don't know about C#, but would something like..
for each(Element ^%e in someArray)  e = gcnew e(...);
Work in C++/CLI? Not something I've tried.

##### Share on other sites
Quote:
 Original post by ShinkageI don't know about C#, but would something like..for each(Element ^%e in someArray) e = gcnew e(...);Work in C++/CLI? Not something I've tried.

If you look at my initial post, that is what I tried to do, but it doesn't work because you can't change values you are foreach'ing over. Also, what does % mean?

##### Share on other sites
I just revisited the documentation of Array, and there is a method ConvertAll<In,Out> (...), which seems to do exactly what I want, except it only takes in one-dimensional arrays. If I understand correctly, a one dimensional array is one without commas, but could have multiple parentheses. Can anyone think of a way to use this method to do what I want or would you recommend starting from scratch?

BTW, I am planning to post the code when and if I come up with a solution.

##### Share on other sites
Quote:
 Original post by yaroslavdIf you look at my initial post, that is what I tried to do, but it doesn't work because you can't change values you are foreach'ing over. Also, what does % mean?

No, what you originally tried to do is in C++/CLI equivalently written thus...
for each(Element ^e in someArray)  e = gcnew e(...);
The % is called a "tracking reference" in C++/CLI and is roughly equivalent to a garbage collected version of the standard C++ reference (&). Mind, this functionality is only available in Visual Studio 2005 since it's part of C++/CLI and not old style Managed C++.

That being said, I booted it up and tried it out, and it does in fact work. The code I originally suggested ( for each(Element ^%... ) will actually set the values within the array. Sorry, but I don't think C# has any equivalent functionality, at least that I know of.

##### Share on other sites
Ok, I re-read the original post and have a bit better understanding:

- You have an array which can potentially have any number of dimensions and any number of nested arrays.
- The most nested array contains a known type (IRecordable in this case).
- You want to create a second array that has the same dimensions and nested array configuration, but the most nested type is different, and is initialized based on the source array's element at that position.

One thing I'm unclear on: Do you already have your destination array created, or does the desired function need to create it from scratch based on the source array?

If your destination array is already created, you could modify my function above to take both the source and destination array. It could iterate through them in parallel with slight modifications. You would have to add a condition to detect when you reached the innermost nested array and do your "destination_element = source_element.Name" conversion.

And to answer your question about multidimensional and one-dimensional arrays, for any multidimensional array, you can convert it to a one-dimensional array like so:

// mutlidimensional formint[,] array = new int[dimension1, dimension2, ... , dimensionN];array[index1, index2, ... , indexN] = 0;// one-dimensional formint[] array = new int[dimension1 * dimension2 * ... * dimensionN];array[index1 + (index2 * dimension1) + (index3 * dimension2 * dimension1) + ...];orarray[index1 + dimension1*(index2 + dimension2*(index3 ... ))];

The downside is that you have to keep track of the dimension1 ... dimensionN values somewhere.

##### Share on other sites
The problem is that I need the destination array to have the exact same dimensions as the source array.

Basically, IRecordable is an interface which my classes can inherit to be recorded (serialized) by my Recorder class. If an IRecordable member is encountered, its Name member (which is a string and represents the location of the object) is recorded. But now I want to extend that to arrays and then later ICollection<IRecordable>. So I can serialize IRecordable arrays by replacing them with string arrays, and deserialize them by deserializing the object at location recorded in each string.

Oh, and about creating the destination array, can't I just do destination = source.Clone()? I mean if I clone it, it will have the same dimensions, right? The types would be wrong, but Array isn't generic, so it should be fine.

Also, I already have recording IRecordable[,,,,,,] working. So as long as I can apply it to IRecordable[][][] I should be fine. I think I got a better idea of how to do it now. Thanks.

##### Share on other sites
If this is solely for serialization / deserialization, you might look into the built-in .Net serialization routines. They're SCARY how much stuff they'll do automatically. They can supposedly figure out how to serialize and deserialize graph data structures that have looping references, etc. I think your array would be easier than that for it to handle.

##### Share on other sites
Well, the reason I'm manually serializing is so that I can store references to IRecordable objects instead of embedding everything in one file. Well, that's the main reason, anyway.