-
Passing arguments
Hello, I'm new to C# and have a problem with argument passing. Every time I pass an object, get some values from it and modify them in a new object, the passed object changes.
Code:
ShipModel first = new ShipModel("1x4", new int[,] {{0,0},{0,1},{0,2},{0,3}});
Ship a1 = new Ship(5, 5, first, false);
Ship a2 = new Ship(5, 5, first, true);
Ship a3 = new Ship(5, 5, first, true);
The code above outputs:
Code:
Inherited... 1x4 @ 0:0 0:1 0:2 0:3
Before moving... 1x4 @ 0:0 0:1 0:2 0:3
After moving... 1x4 @ 5:5 5:6 5:7 5:8
Inherited... 1x4 @ 5:5 5:6 5:7 5:8
Before moving... 1x4 @ 5:5 5:6 5:7 5:8
After moving... 1x4 @ 10:10 10:11 10:12 10:13
Inherited... 1x4 @ 10:10 10:11 10:12 10:13
Before moving... 1x4 @ 10:10 10:11 10:12 10:13
After moving... 1x4 @ 15:15 15:16 15:17 15:18
The initial model is being changed every time a ship is created. the initial coordinates (which should be constant) increases with every adjust(); Tried sealing the model class, did not help.
Code:
public Ship(int xCoord, int yCoord, ShipModel m, bool rotate)
{
x = xCoord; this.y = yCoord;
// inherits coordinates and name from the model
this.coordinates = new List<int[]>(m.getCoords());
this.name = new String(m.getName().ToCharArray());
Console.WriteLine("Inherited... " + this.ToString());
if (rotate) this.rotate();
this.adjust();
}
private void adjust()
{
// moves the ship
Console.WriteLine("Before moving... " + this.ToString());
for (int i = 0; i < this.coordinates.Count; i++)
{
this.coordinates[i][0] += this.x;
this.coordinates[i][1] += this.y;
this.coordinates[i][2] = 0;
}
Console.WriteLine("After moving... " + this.ToString());
}
Code:
class ShipModel
{
private List<int[]> coordinates = new List<int[]>();
private String name;
public ShipModel() { }
public ShipModel(String name, int[,] coordinates)
{
this.name = name;
for (int i = 0; i < (coordinates.Length / 2); i++)
{
this.coordinates.Add(new int[] { coordinates[i, 0], coordinates[i, 1], 0 });
}
}
public String getName()
{
return this.name;
}
public List<int[]> getCoords()
{
return this.coordinates;
}
}
-
Re: Passing arguments
-
Re: Passing arguments
Because when you pass a reference to a method you are not passing a copy of the object itself, you are passing a copy of the reference, i.e., any modifications to the original object will be persisted. If you want copy semantics you should use a struct instead of a class, but be warned that, even then, references maintained by the struct will be copied, but not what they refer to (i.e., your List member will be copied, but only the reference, not the contents of the List itself).
On a side note, declaring a class sealed means only that it cannot be inherited from, it has nothing to do with copy semantics.
-
Re: Passing arguments
Thank you. Is there any way to only copy contents of the object?
-
Re: Passing arguments
-
Re: Passing arguments
As long as performance is acceptable that would work just fine. If not, you could always call the MemberwiseClone on your class. It creates a new instance of your class and copies the values of the fields to the new instance. If you have any reference fields in your class you'll also need to memberwise clone them and replace the reference on the new object. If you don't, you'll end up with the same object reference stored in multiple places which is what caused your original problem.