This question already has answers here:
Passing Arrays by Value and by Reference
(4 answers)
Closed 5 years ago.
I have a jagged array that I pass to object constructor but whenever I edit the array that I passed as parameter, the array inside the instance of the object also gets edited for some reason.
bool[][] clickedArray = new bool[7][];
clickedArray[0] = new bool[3];
clickedArray[1] = new bool[3];
clickedArray[2] = new bool[3];
clickedArray[3] = new bool[2];
clickedArray[4] = new bool[3];
clickedArray[5] = new bool[3];
clickedArray[6] = new bool[4];
I read some ints from a file and set the bools to true or false depending on the ints. By default, all elements of the jagged array are set to false:
for (int i = 0; i < clickedArray.Length; i++) // i < 7
{
for (int j = 0; j < clickedArray[i].Length; j++)
{
clickedArray[i][j] = false;
}
}
I also have a List of objects. I call the constructor by adding new instance of the object to the list: buildsList.Add(new Builds(tokens[0], clickedArray));
Here is the constructor:
public Builds(string buildName, bool[][] jagged)
{
this.buildName = buildName;
jaggedArray = jagged;
}
I don't know why but when I, for example, reset the array and then call a function such as:
int selection = comboBox1.SelectedIndex;
clickedArray = buildsList[selection].getJaggedArray();
it turns out that the jagged array from the object inside the list also had it's values reset.
Arrays in .NET are object on the heap, so you have a reference. That reference is passed by value, meaning that changes to the contents of the array are reflected anywhere.
So: jaggedArray = jagged;
they have the same reference pointer to the same address in the memory.
Use Array.Copy method to avoid that issue in order to copy elements fr
om the source array to the destination. Check how to use Array.Copy Method.
Related
Given a class:
class clsPerson { public int x, y; }
Is there some way to create an array of these classes with each element initialized to a (default) constructed instance, without doing it manually in a for loop like:
clsPerson[] objArr = new clsPerson[1000];
for (int i = 0; i < 1000; ++i)
objArr[i] = new clsPerson();
Can I shorten the declaration and instantiation of an array of N objects?
The constructor must be run for every item in the array in this scenario. Whether or not you use a loop, collection initializers or a helper method every element in the array must be visited.
If you're just looking for a handy syntax though you could use the following
public static T[] CreateArray<T>(int count) where T : new() {
var array = new T[count];
for (var i = 0; i < count; i++) {
array[i] = new T();
}
return array;
}
clsPerson[] objArary = CreateArray<clsPerson>(1000);
You must invoke the constructor for each item. There is no way to allocate an array and invoke your class constructors on the items without constructing each item.
You could shorten it (a tiny bit) from a loop using:
clsPerson[] objArr = Enumerable.Range(0, 1000).Select(i => new clsPerson()).ToArray();
Personally, I'd still allocate the array and loop through it (and/or move it into a helper routine), though, as it's very clear and still fairly simple:
clsPerson[] objArr = new clsPerson[1000];
for (int i=0;i<1000;++i)
clsPerson[i] = new clsPerson();
If it would make sense to do so, you could change class clsPerson to struct Person. structs always have a default value.
This question already has answers here:
All possible array initialization syntaxes
(19 answers)
Closed 5 years ago.
What is the language grammatical problem in my code?
I want to declare an array of queues. Is this the right way to declare and use them?
public static void Main(string[] args)
{
Queue<int>[] downBoolArray = new Queue<int>[8]();
downBoolArray[0].Enqueue(1);
}
Your first problem is a syntax error: new Queue<int>[8]() should be new Queue<int>[8].
Once declared with the correct syntax, when you attempt to use an element of the array (downBoolArray[0].Enqueue(1)) you will encounter a NullReferenceException because array elements initialise to their default values which in the case of a reference type is null.
You could instead initialise your array with non-null seed values using a single line of LINQ:
Queue<int>[] downBoolArray = Enumerable.Range(1,8).Select(i => new Queue<int>()).ToArray();
The arguments to Range specify that we need 8 'entries' in our sequence; the Select statement creates a new Queue<int> for each item; and the ToArray call outputs our sequence as an array.
You need to initialize each element in your array
void Main()
{
Queue<int>[] downBoolArray =new Queue<int>[10];
for (int i = 0; i < downBoolArray.Length; i++)
downBoolArray[i] = new Queue<int>();
downBoolArray[0].Enqueue(1);
}
You've created an array of null values.
What you want is something like this:
public static void Main(string[] args) {
var queues = new Queue<int>[8];
// Possibly some other stuff
// Initialise all values
for (var i = 0; i < queues.Length; i++) {
// Accounting for maybe already sporadically initialising values
queues[i] = (queues[i]) ?? new Queue<int>();
}
// Do whatever
}
I have a typed array MyType[] types;
and i want to make and independant copy of this array. i tried this
MyType[] types2 = new MyType[types.Length] ;
types2 = types ;
but this create a reference to the first. I then tried
Array.Copy( types , types2 , types.Length ) ;
but I have the same problem: changing a value in the first array changes the value in the copy as well.
How can I make a completely independent or deep copy of an Array, IList or IEnumerable?
Based on the first post, all he needs is this for "an independent copy of the array". Changes to the shallowCopy array itself would not appear in the types array (meaning element assignment, which really is what he showed above despite saying "deep copy"). If this suits your needs, it will have the best performance.
MyType[] shallowCopy = (MyType[])types.Clone();
He also mentions a "deep copy" which would be different for mutable types that are not recursive value-type aggregates of primitives. If the MyType implements ICloneable, this works great for a deep copy:
MyType[] deepCopy = (MyType[])Array.ConvertAll(element => (MyType)element.Clone());
For the impatient:
newarray = new List<T>(oldarray).ToArray();
Implement a clone method on MyType, using protected method MemberwiseClone (performs shallow copy) or using a deep cloning technique. You can have it implement an ICloneable then write several extensions methods that will clone the corresponsing collection.
interface ICloneable<T>
{
T Clone();
}
public static class Extensions
{
public static T[] Clone<T>(this T[] array) where T : ICloneable<T>
{
var newArray = new T[array.Length];
for (var i = 0; i < array.Length; i++)
newArray[i] = array[i].Clone();
return newArray;
}
public static IEnumerable<T> Clone<T>(this IEnumerable<T> items) where T : ICloneable<T>
{
foreach (var item in items)
yield return item.Clone();
}
}
You must do this because while a new array is created when you use Array.Copy it copies the references, not the objects referenced. Each type is responsible for copying itself.
If your type is serializable you can use serialization techniques to get a copy of your array (including deep copies of the items):
private static object GetCopy(object input)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, input);
stream.Position = 0;
return formatter.Deserialize(stream);
}
}
To use it:
MyType[] items = new MyType[2];
// populate the items in the array
MyType[] copies = (MyType[])GetCopy(items);
I wanted to do the same thing: make a copy of an array by value for things like sorting so that I could later reinitialize another temp array with the original source array. After researching this, I found this cannot be done so simply. So, I made a workaround. I will use my own code below:
string[] planetNames = new string[] { "earth", "venus", "mars" };
string[] tempNames = new string[planetNames.Length];
for (int i = 0; i < planetNames.Length; i++)
{
tempNames[i] = planetNames[i];
}
planetNames is my source array. tempNames is the array which I will later sort independently of planetNames. I have tested this and this code does not sort planetNames when I sort tempNames which is what I was attempting to achieve.
If you want to create a copy of just an array with references to objects in old array (or if you have array of value type objects), simplest solution is
var newArray = oldArray.ToArray()
If you want deep copy you should have a method which copies single object of your type (e.g. public MyType Copy(MyType obj)). Then solution will look like
var newArray = oldArray.Select(x => Copy(x)).ToArray()
I've found if you just want a simple char array copy you can trick C# into doing a copy by value using the char:
char[] newchararray = new char[desiredchararray.Length];
for (int k = 0; k < desiredchararray.Length; k++)
{
char thecharacter = newchararray[k];
newchararray[k] = thecharacter;
oldchararray[k] = oldchararray[k] + 1;
}
Seems to work for me but if anyone disagrees please let me know :)
Copying the value of the array in this case are numbers
int[] arr = { 1, 2, 3, 4, 5 };
int[] copyArr = new int[arr.Length];
for (int i = 0; i <arr.Length; i++)
{
copyArr[i]=arr[arr.Length-i-1];
}
Console.WriteLine(string.Join(" ",arr));**
I'm creating one object by using values from other object.Like that:
MAP.cs
int[][] map = {......};
Mob m = new Mob(0,0,map);
And calling Mob's class function Move()
m.Move();
Move function looks like this:
int xp = (int)Math.Floor(x / 32);
int yp = (int)Math.Floor(y / 32);
int[] result = lookForClosest(xp, yp);
this.nextX = result[1];
this.nextY = result[0];
map[this.nextY][this.nextX] = 1;
Functions are called using DispatcherTimer in another class(MainWindow)
The result of this application is that map property in MAP class is changed. The only change made should be in the Mob object's map property. Any explanation and possible fix?
Arrays are reference types, so when you call
Mob m = new Mob(0,0,map);
You are passing a reference to the array to the Mob constructor, and any changes you make to the array in the Mob class will be reflected in the source array. You can change this one of two ways:
Clone the array before passing it to the Mob class, or
Clone the array within the Mob constructor.
From a ownership perspective, the question is - should clients expect to see changes to the array, or is the array more of a "seed" input that can be modified within the class?
Also note that you have an array of arrays, so you not only need to close the "outer" array, but each of the arrays within it:
public T[][] Clone<T>(T[][] source)
{
T[][] output = new T[source.Length][];
for(int i=0; i<source.Length; i++)
output[i] = (T[])source[i].Clone();
return output;
}
or if you're comfortable with Linq:
public T[][] Clone<T>(T[][] source)
{
return source.Select(a => (T[])a.Clone()).ToArray();
}
I have a multidimensional jagged string array:
string[,][] MDJA =
{
{new string[]{"a", "b"}, new string[]{"c", "d"}, new string[]{"e", "f"}},
{new string[]{"g", "h"}, new string[]{"j", "i"}, new string[]{"k", "l"}},
{new string[]{"m", "n"}, new string[]{"o", "p"}, new string[]{"q", "r"}}
}
I'm using for-loops to compare the placement of the arrays inside the array to get the array I'm looking for, but the MDJA is inside a method and i would like it to return the specific array. As an example i might want to return
new string[]{"m", "n"}
Normally I would do this in a multidimensional-array:
for (byte i = 0; i < 3; i++)
{
if (var1[x] == var2[i])
{
return answers[y,i]
}
}
But i haven't used jagged arrays before and when using them multidimensionally it made it harder to get information.
P.S The 4 variables are arguments in the method, var1 and var2 are string arrays and x/y are integers.
Thank you for helping.
I am not quite sure what your method logic looks like but regarding element access it should be quite trivial:
for (int i = 0; i < MDJA.GetLength(0); i++)
{
for (int j = 0; j < MDJA.GetLength(1); j++)
{
// Your compare logics go here
//
bool found = i == 2 && j == 0;
if (found)
{
return MDJA[i, j];
}
}
}
This will return the string[]{"m", "n"}.
I've done this before, alas I do not have the code here with me.
Build a utility method that calls itself recursively, tests whether an array element is an array itself, if it is not (and so a value) add it to a List, otherwise pass the sub/child array to the recursive method.
Hint, use Array object as the parameter for this method, rather than a defined int[,][] array, thus any form of crazy int[,][][][,,,][][,] can be passed and will still work.
And for your problem, you would have to detect at what level you wish to stop transforming from jagged arrays to values, and then returning those jagged arrays, in a simplified array.
I will post my code later, it may help you.
public static int Count(Array pValues)
{
int count = 0;
foreach(object value in pValues)
{
if(value.GetType().IsArray)
{
count += Count((Array) value);
}
else
{
count ++;
}
}
return count;
}