Home > Software design >  C# List is adding incorrect members
C# List is adding incorrect members

Time:10-21

I am trying to add a few different members to a list, but when the list is added to it contains copies of only the last member added:

    private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
    {
        for (Track trytrack = Track.Empty   1; trytrack < Track.MaxVal; trytrack  )
        {
            if (validMove(ps.nextSide, trytrack))
            {
                ps.SetCell(trytrack);
                possibleTracks.Add(ps);
            }
        }
        return tryNextTrack(ps, possibleTracks);
    }

The PotentialSolution class looks like this:

public class PotentialSolution
{
    public Track[,] board;
    public Side nextSide;
    public int h;
    public int w;
    static int cellsPerSide;
    static bool testing;
    static int minTracks;
    .....
    public void SetCell(Track t)
    {
        board[h, w] = t;
    }
}

So we are trying to make several copies of the board which only differ by which 'track' is placed in the current cell. If I have a breakpoint at possibleTracks.Add(ps) then I can see by inspecting ps that the required cell contents is changing each time, as required. But when the code reaches the next line (or the return statement), the cell content is the same in each member of the list (it's the last one that was added). What I am doing wrong here? I have tried using an ArrayList and also a basic array instead, but get the same result. It's acting as though the board member is decared as static, but it's not.

CodePudding user response:

You are adding references to the same object: ps in possibleTracks.Add(ps)

You could add a constructor to PotentialSolution duplicating the class:

public class PotentialSolution
{
    public Track[,] board;
    public Side nextSide;
    public int h;
    public int w;
    static int cellsPerSide;
    static bool testing;
    static int minTracks;
    //.....
    public PotentialSolution()
    {
    }
    public PotentialSolution(PotentialSolution ps)
    {
        board = ps.board;
        nextSide = ps.nextSide;
        h = ps.h;
        w = ps.w;
    }
    //.....

Then use:

  private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
    {
        for (Track trytrack = Track.Empty   1; trytrack < Track.MaxVal; trytrack  )
        {
            if (validMove(ps.nextSide, trytrack))
            {
                ps.SetCell(trytrack);
                possibleTracks.Add(new PotentialSolution(ps)); // duplicate object
            }
        }
        return tryNextTrack(ps, possibleTracks);
    }

This creates a new instance of the class each time it is added to the list.

CodePudding user response:

You always call SetCell on the same ps object you received as a parameter then add the same instance to the possibleTracks list. The result is: possibleTrack contains ps n times and because it is the same instance you used in each cycle it will have the last change you applied via SetCell call.

Not sure what you wanted to achieve but it looks you need a modified copy of ps in each cycle for adding to possibleTrack list. Making PotentialSolution a struct instead of class could be enough? Structs are copied in such a way but may hit your performance if PotentialSolution is big.

The board member will still generate the same problem, because despite ps will be copied but the board inside it will contain same Track references. The trick can be applied to Track too, but the performance issues may raise more.

Just implement a Clone on PotentialSolution to have fully detached instances of it, then call ````SetCell``` on cloned instance and add that instance to the list.

  • Related