Why changing one array changes another array in C#? - c#

I have a two dimensional array namely States in C#. I build a one dimensional array, namely SubState, from States. When I change SubState, States changes too. I want States be unchanged. Thanks
int[] SubState = State [0];
SubState[0]-=1; //State[0][0] is also changed here

In my mind your State definition is:
int[][] State;
Array is a reference type and when you copy an element from the State array you get a reference to the array from the first list and the both references map to the same int[] array. So when you change array stored at SubArray you use a link to the same array.
The simple fix is a copy of the source array
var SubState = State[0].ToArray();

That is because when you assign the array you pass its reference you are not making a copy of it. Look at the msdn link on the array copy method https://msdn.microsoft.com/en-us/library/System.Array.Copy(v=vs.110).aspx

int[] SubState = State [0]; is just another reference to the state array and so can be changed via it as well.
What you probably want to do, is create a separate array from the state array like
int[] substate = new int[state.GetLength(0)];
state.CopyTo(substate, 0);

You are not building a new one-dimensional array. You are simply creating a new reference to the first row of your two-dimensional array. If you actually want to build a new one-dimensional array, you have to iteratively copy the first row of your two-dimensional array.
Try:
int[] SubState = new int[States[0].length];
States[0].CopyTo(SubState, 0);

instead of
int[] SubState = State [0];
try
int[] SubState = new int[State[0].Length];
Array.Copy(State[0],Substate, Substate.Length)
So you are not simply assigning a new reference, but are actually copying the array correctly

Obviously your element at position 0 of State is an array of int which is a reference-type. Thus both SubState and State reference the same array which is why changes to any of their elements are reflected by both. To overcome this problem you may create a copy of your State-array and copy its values to SubState:
States.CopyTo(SubStates, 0);
EDIT: Thius assumes that SubStates was already initialized with the same size as States. e.g:
int[] SubStates = new int[States[0].Length];

Related

(Array.Clone) Shallow Copy vs Deep Copy of an Array

int[] myArray = {1, 2, 3, 4, 5};
Console.WriteLine(myArray[0]);
int[] localArray = (int[])myArray.Clone();
localArray[0] = 10;
Console.WriteLine(myArray[0]);
Console.WriteLine(localArray[0]);
The output of the following was:
1
1
10
As to my understanding, both myArray[0] and localArray[0] should point to the same integer, and if I change localArray[0] to 10, it should reflect upon myArray[0] as well. But as the output suggests they both point to different integers. What's going on here?
A Shallow Copy of an Array is not the same as a copy of an array:
Copying an array, copies the reference to the array to a new variable. Both variables will be pointing to the same values.
The Clone method creates a new, distinct array containing a copy of the elements of the original array. If those elements are value types (like in your case ìnt) the new array will contain the same set of values as the original but stored in another location.
If the elements of the array are of a reference type, the new array will contain copies of the original references. So the first elements of both array would contain the same reference to an object.
See also: https://learn.microsoft.com/en-us/dotnet/api/system.array.clone?view=net-6.0
A shallow copy of an Array copies only the elements of the Array, whether they are reference types or value types, but it does not copy the objects that the references refer to. The references in the new Array point to the same objects that the references in the original Array point to.
If elements are value type then "Shallow Copy" == "Deep Copy" (as "int' in this case).
In case if elements are reference type then "A Shallow Copy of an Array is not the same as a copy of an array:" and below as wrote the #Johan Donne

How to make the array size a ReadLine?

I'm trying to make a sorting algorithm and asking the user to input the array size is a must. I am a beginner in C# so I don't have any idea how to do that.
This is the idea that came to my mind, but I'm having an error.
Console.WriteLine("Enter how many elements you want to be sorted:");
a = Convert.ToInt32(Console.ReadLine());
int[] MyArray= new int[a] {""};
Visual Studio says that 'a constant value is expected'. How could I make the array length a ReadLine? My goal is for the user to decide which array length they want the program to show and that the elements inside the array would be system generated based on the array length that the user chose.
You can initialise an array like this:
int[] MyArray= new int[a];
But, I would also point out, that you could use a dynamic collection (such as a list), then you don't need to ask up front how many items, you just keep adding items until the user decides to stop.
ICollection<int> myCollection = new List<int>();
myCollection.Add(1);
myCollection.Add(1);
The type of your array is int but you are trying to initialize it with an empty string. In C# you can declare an array in a few ways. You can declare it by providing a size as in:
int[] myArray = new int[size];
And initialize the values later.
An alternative is to instantly intialize it with values like this:
int[] myArray = new int[] { 1, 2, 3 };
Note that when using the second option, you shouldn't provied the size as the compiler will infere it.

Storing lots of Arrays into a List on every Loop

I have a question about storing lots of arrays into a list.
First, I initialize the array and list:
int[] arr = new int[9];
List<int[]> forkarr = new List<int[]>();
then I run through a lot of for loops and modify the array each time in order to produce all possible tic tac toe variations. While looping through all those variations, if the array is a possible board then I print it, and additionally if the array meets certain criteria for being a 'fork', then I will add it to the list like this:
if (ForkCheck.fork(arr)) { forkarr.Add(arr); Console.WriteLine("It's a Fork!");}
which also prints that message letting you know that particular array is a fork.
Now, when I am printing all of the arrays, the ones that are forks are printed properly and labeled as such.
However, when I go to print out all of the int[] elements of my list forkarr like so:
foreach (int[] arry in forkarr)
{
PrintGame.print(arry);//this is my method that prints the array
Console.WriteLine();
}
for some reason each array becomes an identical:
222
222
222
(I'm using 2 as 'X' and 1 as 'O' and 0 as 'empty' btw)
And it just prints that out over and over for all the forks.
So, something is going wrong when I am adding each modification of the array as a new element in the list I think, but I'm not sure why.
Thanks for any help.
Because you are modifying the same array and adding it to the list. Each time you done with one array array you need to create a new instance like this:
arr = new int[9];
This will create a new reference which will be independent from other arrays. And modifying it's elements wont affect the others.
For more information about value vs reference types you can refer to the question below:
What is the difference between a reference type and value type in c#?

How to delete an element from an array[,]?

I want to remove an element of this array
int[,] numbers = { {1,0} , {3,4} , {9,2} , {4,0} };
int[,] Remove = {{4,0}};
You cannot remove items from an Array because they are a fixed size I would use:
List<Tuple<int,int>>
this way you still have a list of two dimensional objects with the ability to remove them as well using
List.Remove()
You can't - arrays are fixed size. You can set the value to null. Best is to use generic collections such as List<int[]> which will allow you to add, insert and remove values.

C#: Is there a way to resize an array of unknown type using reflection?

My users pass me an array of some type, say int[] or string[]. I can easily query the types of the elements via GetElementType, and I can find out how long the array was when it was passed to me via GetRank, GetLength, etc.
The arrays are passed in a params list, so visualize code like this:
public void Resizer(params object[] objs)
{
foreach (object o in objs)
Array.Resize(ref o, 3);
}
What I would like to do is the converse of the Get methods that are available and that do work: I want to resize the array that was passed to me, setting the length to some other length (like 3 in this silly example).
I'm doing this because in my setting the array will contain data received from a set of cloud computing servers and we can't know how many will respond in advance, hence can't preallocate the array to have the right length. Ideally, in fact, my user passes in an array of length 0, and I pass back an array of length n, signifying that I got n replies from the servers that were queries.
I can't do this with Array.Resize(ref T, int) because I don't know T at compile time.
Is there a way to pull this off?
This should work:
static void Resize(ref Array array, int newSize) {
Type elementType = array.GetType().GetElementType();
Array newArray = Array.CreateInstance(elementType, newSize);
Array.Copy(array, newArray, Math.Min(array.Length, newArray.Length));
array = newArray;
}
Why not just create a new array of whichever type you need that is the size that you want? Then populate it from the array you want to resize, setting non existent values to some default.
In case anyone is curious, I ended up switching my code to use List
I agree with the comments that you should be using List(Of T), but if you want to copy your array into a new array of the same type, you could do something like the following.
// Your passed in array.
object[] objs = new object[5] {1,2,3,4,5};
// Create an array of the same type.
Array a = Array.CreateInstance(objs[0].GetType(), objs.Length+3);
// Copy in values.
objs.CopyTo(a,0);
I guess I'll just switch to using Lists, but this is a shame; the code will be quite a bit messier looking and since my users are basically at the level of first-semester ugrads, each little thing will make their lives less good. But I'm suspecting that you folks don't see a way to do this either. Oh well....

Categories