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();
}
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.
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));**
In the main program class I have:
static void Main()
{
string[,,] anArray = new string [3,3,3];
anArray[0,0,0] = "value1";
anArray[0,0,1] = "value2"; .... //filling the rest of the array.
}
How can I pass this array into another separate class "anotherClass" using a constructor with multiple arguments like:
class AnotherClass
{
private string[,,] anotherClassArray;
public string[,,] AnotherClassArray
{
get { return anotherClassArray;}
}
public AnotherClass (string[,,] fromAnArray)
{
anotherClassArray = new string [fromAnArray.Length];
}
}
I've seen examples with just a simple 1 dimensional array being passed from the Main program into another separate class and back again but when I tried following the same example for a multidimensional I get the error:
"Cannot implicitly convert type 'string[]' to 'string[,,*]'" when trying to initialize the new array.
If you want AnotherClass to have it's own separate, empty, instance of a 3D array, then you can do what Pikoh said. In this case, if you change the contents of the array, the original array created in Main is unaffected, and vice versa.
If you want AnotherClass to reference the same array as the one created in Main, and therefor have access to it's same, filled in contents, then simply set the AnotherClass.anotherClassArray reference to equal fromAnArray in the AnotherClass constructor like so:
public AnotherClass (string[,,] fromAnArray)
{
anotherClassArray = fromAnArray;
}
You can do it like this:
string[, ,] anotherClassArray = new string[anArray.GetLength(0),
anArray.GetLength(1),
anArray.GetLength(2)];
Update
As a experiment, if you want make this to generic for any unknown number of dimensions, you can use this method:
private Array CreateArrayWithSameDimensions(Array inArray)
{
int[] lengths = new int[inArray.Rank];
for (int i = 0; i < inArray.Rank; i++)
{
lengths[i] = inArray.GetLength(i);
}
Array myArray = Array.CreateInstance(typeof(string), lengths);
return myArray;
}
The problem with this approach is that accessing this array is not as simple as with known dimensions. This is an example of usage:
Array myArray = CreateArrayWithSameDimensions(anArray);
int[] indices = new int[anArray.Rank];
for (int i = 0; i < anArray.Rank; i++)
{
indices[i] = 0;
}
myArray.SetValue("test", indices);
This would set test in the lower bound index of that array. If the input array was a 3 dimensional array, in myArray[0,0,0] we would have test.
CardDetails is a Structure.
public static void ParceIntricaciesJabber(ref CardDetails[] WhichArray)
{
WhichArray[0].ID = 50;
WhichArray[0].Type = "None";
}
In calling:
ParceIntricaciesJabber(ref OpponentCards);
After I call the function though, another Array called PlayerCards is affected in the exact same way as OpponentCards - despite being declared as two different arrays. They have the same number of elements and the same data Type, and that's it.
This probably should be obvious but i'm not seeing it. The code works in VB.NET. What am I doing wrong?
EDIT: Initialization Code:
public static class Module1{
public static CardDetails[] PlayerCards = new CardDetails[100];
public static CardDetails[] OpponentCards = new CardDetails[100];
}
And also when navigating to the Form
for (int n = 1; n <= 100; n++)
{
Module1.PlayerCards[n] = new CardDetails();
Module1.OpponentCards[n] = new CardDetails();
}
My guess is that you are sharing the reference to the arrays. Even though it is structs inside the array, the array itself is a reference type. You will need to post your array instantiation code to verify one way or the other though
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));**