'Change to array triggers change in other object

I am currently working on a chess game and I want to implement a Redo button. The way i am doing this is, that the I have a list of GameStateContainer class which holds the GameGrid observablecollection. But whenever a move is done and the GameGrid collection is changed, it gets changed in every member of the gameStateContainer list.

This is getting executed after every move done.

            this.gameStateContainer.Add(new GameStateContainer(this.GameGrid.ToList(), this.Moves.ToList(), this.PiecesDown.ToList(), this.currentPlayer));

And with this method call, every member of the list gets changed:

            this.GameGridModel.ExecuteMove(source.Cell, destination.Cell);

This method does nothing else than this:

            this.Grid[source.Row, source.Column].Piece = null;
        this.Grid[destination.Row, destination.Column].Piece = movedPiece;

So how could I actually save the GameGridModel after every move?



Solution 1:[1]

You are not creating copies of the elements inside the collection. MyCollection.ToList() only creates a new List<T> instance, but this instance contains the same elements. You must also copy the elements.

You can achieve this either by implementing your data structures as struct (value type) or by using object.MemberwiseClone or a copy constructor. Depending on your objects, you would have to create a deep copy, which would eliminate object.MemberwiseClone.

The following example shows how to implement cloning:

public class Person
{
    public int Age;
    public string Name;
    public IdInfo IdInfo;

    public Person ShallowCopy()
    {
       return (Person) this.MemberwiseClone();
    }

    public Person DeepCopy()
    {
       Person other = (Person) this.MemberwiseClone();
       other.IdInfo = new IdInfo(IdInfo.IdNumber);
       other.Name = String.Copy(Name);
       return other;
    }
}

Now to clone a collection of Person, you will have to call DeepCopy on each:

var persons = new List<Person>() { new Person { Age = 1 } };
var personClones = persons
  .Select(person => person.DeepCopy())
  .ToList();

/* Now, modifying the elements in 'persons' won't modify the clones in 'personClones' */
persons[0].Age++;
var personAge = persons[0].Age; // 2
var personCloneAge = personClones[0].Age; // 1

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1