user648132
user648132

Reputation: 115

C# ArrayList.Add() overwriting previous objects on add

I have written a simple method that receives a Generic that I wish to place into an ArrayList using the ArrayList.Add() method. However I have discovered that when I go add a new item with the same type as previous items in the ArrayList this new item overwrites the previous items individual properties.

Here's the code its pretty basic and rather embarrassingly I can't seem to rectify this overwriting problem.

public class ChromosomeTree<T>
{
    private GeneNode<T> root;
    private ArrayList children = new ArrayList();
    private int depMax;

    string stemp;

    public ChromosomeTree()
    {
        root = null;
    }

    public virtual void Clear()
    {
        root = null;
    }

    public GeneNode<T> Root
    {
        get
        {
            return root;
        }
        set
        {
            root = value;
        }
    }

    public int MaxDepth
    {
        get
        {
            return depMax;
        }
        set
        {
            depMax = value;
        }
    }

    public ArrayList Children
    {
        get
        {
            return children;
        }
    }

    public GeneNode<T> lastChild()
    {
        return (GeneNode<T>)this.Children[this.Children.Count - 1];
    }

    public void addFull(GeneNode<T> node)
    {
        //check if the chromosome tree has a root if not add the first node as the chromosomes root

        if (this.Root == null)
        {
            this.Root = node;
            children.Add(node);
            stemp += " " + node.Value;
        }
        else
        {
            for (int i = 0; i <= this.Children.Count - 1; i++)
            {
                GeneNode<T> parent = (GeneNode<T>)this.Children[i];

                //check to ensure maxDepth of chromosome tree is not exceeded
                if (parent.Depth != this.MaxDepth)
                {
                    //check to see if the current node stil has room for another node to be added to it
                    if ((parent.Children == null) || (parent.Children[1] == null))
                    {
                        children.Add(node);
                        parent.Add(node);

                        stemp += " " + node.Value;

                        break;
                    }
                }
                else
                {
                    break;
                }
            }
        }
    }

    public override string ToString()
    {
        string chromosome = String.Empty;

        foreach(GeneNode<Gene> gene in this.Children)
        {
            chromosome += " " + gene.Value.GeneValue.ToString();
        }

        return chromosome;
    }
}

Im pretty sure its a simple mistake but ive looked at this for so long I cant see the wood from the trees. Any thoughts would be greatly appreciated.

Many thanks in advance.

Luke

here is the code that utilises the this class.

EDIT : THE OVERWRITE HAPPENS WHEN THE METHOD IS CALLED NOT AFTER THE METHOD HAS EXECUTED ITS LOGIC

 class SimpleChromosome
{
    Random rand = new Random();

    Gene funcGene = new Gene();
    Gene termGene = new Gene();

    private string sChromosome;

    private int currentdepth;

    private string grownChromosome()
    {
        return sChromosome;
    }

    public ChromosomeTree<Gene> fullChromosome()
    {
        ChromosomeTree<Gene> chromosone = new ChromosomeTree<Gene>();
        //chromosone.MaxDepth = rand.Next(1, 5);
        chromosone.MaxDepth = 1;

        int maxGenes = (int)Math.Pow(2, chromosone.MaxDepth + 1) - 1;

        for (int i = 0; i <= chromosone.MaxDepth; i++)
        {
            int numNodesForLevel = (int)Math.Pow(2, i);
            int numNodesOnLevel = 0;

            for (int j = 0; j < numNodesForLevel; j++)
            {
                if (currentdepth != chromosone.MaxDepth)
                {
                    funcGene.GenerateValue(GeneType.Function);
                    GeneNode<Gene> geneNode = new GeneNode<Gene>(funcGene);
                    sChromosome += " " + geneNode.Value;
                    chromosone.addFull(geneNode);

                    numNodesOnLevel++;
                }
                else
                {
                    termGene.GenerateValue(GeneType.Terminal);
                    GeneNode<Gene> geneNode = new GeneNode<Gene>(termGene);
                    sChromosome += " " + geneNode.Value;
                    chromosone.addFull(geneNode);

                    numNodesOnLevel++;
                }

                if ((numNodesForLevel == numNodesOnLevel) && (currentdepth != chromosone.MaxDepth))
                {
                    currentdepth++;
                }
            }
        }
        currentdepth = 0;

        //Console.WriteLine("Before ADD :" + sChromosome);

        sChromosome = "";

        return chromosone;
    }
}

Upvotes: 0

Views: 4652

Answers (3)

Jamie Treworgy
Jamie Treworgy

Reputation: 24334

in this loop parent == Children[i] and Children is a getter for children

Do you really mean to be adding the same node to children and parent, which would make the same node a sibling of parent in addition to a child? I'm not clear on what you're really trying to do but this seems wrong:

    if ((parent.Children == null) || (parent.Children[1] == null))
     {
          children.Add(node);
          parent.Add(node);
..
     }

edit

From the supporting code you posted the problem could be related to how you create objects:

/* outside the loop */
    Gene funcGene = new Gene();
    Gene termGene = new Gene();

...

/* inside the loop*/
    funcGene.GenerateValue(GeneType.Function);
    GeneNode<Gene> geneNode = new GeneNode<Gene>(funcGene);
    sChromosome += " " + geneNode.Value;
    chromosone.addFull(geneNode);

Seems like you are create a new GeneNode multiple times using a one of two instances of Gene in its constructor. Assuming that your GeneNode is saving that as a property value, each GeneNode is going to reference the same instance of Gene (well, one of two, either funcGene or termGene). I'm guessing this is what you mean when you say new item with the same type as previous items in the ArrayList this new item overwrites the previous items individual properties. Any changes to a Gene property assigned from the constructor in any node of the same type will refer to the same Gene. Even though you are creating new GeneNodes they are constructed from the same Gene.

So assuming that GeneNode.Value references the Gene that it was constructed with, there can only be two different values returned (corresponding to the the current value of one of the two Gene instances) by any node at any given point in time.

Probably, you want to move the code to create a new Gene inside your loop.

Upvotes: 0

user648116
user648116

Reputation: 41

For this sort of relationship you really should be coding to interfaces. eg.

public interface IGeneNode{
  //genenode definition including perhaps equality interfaces etc
}

If the above is correct then you can overload your Assignment operator to pass the values you wish to pass.

This might be useful to you as well.

C# - Multiple generic types in one list

Upvotes: 1

Saeb Amini
Saeb Amini

Reputation: 24390

Post the code where you are adding a new object of this type to your ArrayList.

My guess is that you are using two references to the same object.

Remember that objects are reference types, therefore if you assign them to each other you are only assigning their references. e.g. in the following code:

Foo foo1 = new Foo();
foo1.x = 1;
Foo foo2 = new Foo();
foo2.x = 2;

foo2 = foo1; // foo2 now points to the same object as foo1;
// foo1.x does not get copied into foo2.x.
// You have also lost your reference to the original foo2 object here and it will be garbage collected.
foo2.x = 100;
// since foo2 and foo1 are now pointing to the same object. both foo2.x and foo1.x will be 100

Upvotes: 1

Related Questions