C # ArrayList.Add () перезаписывает предыдущие объекты при добавлении - PullRequest
0 голосов
/ 07 марта 2011

Я написал простой метод, который получает Generic, который я хочу поместить в ArrayList, используя метод ArrayList.Add ().Однако я обнаружил, что когда я добавляю новый элемент того же типа, что и предыдущие элементы в ArrayList, этот новый элемент перезаписывает индивидуальные свойства предыдущих элементов.

Вот код, довольно простой и довольно неловкий, который я могу 'Похоже, это исправляет эту проблему с перезаписью.

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;
    }
}

Я уверен, что это простая ошибка, но я смотрел на это так долго, что не вижу дерево с деревьев.Любые мысли будут с благодарностью.

Большое спасибо заранее.

Люк

вот код, который использует этот класс.

РЕДАКТИРОВАТЬ: ПЕРЕЗАПИСЬ ПРОИСХОДИТ, КОГДА МЕТОД ВЫЗЫВАЕТСЯ, НЕ ПОСЛЕ ТОГО, КАК МЕТОД ВЫПОЛНИЛ ЕГО ЛОГИКУ

 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;
    }
}

Ответы [ 3 ]

1 голос
/ 07 марта 2011

Для такого рода отношений вы действительно должны кодировать интерфейсы. например.

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

Если вышеприведенное верно, вы можете перегрузить свой оператор присваивания, чтобы передать значения, которые вы хотите передать.

Это может быть полезно и вам.

C # - Несколько универсальных типов в одном списке

1 голос
/ 07 марта 2011

Опубликуйте код, где вы добавляете новый объект этого типа в ваш ArrayList.

Я предполагаю, что вы используете две ссылки на один и тот же объект.

Помните, что объектыссылочные типы, поэтому, если вы назначаете их друг другу, вы только назначаете их ссылки.например, в следующем коде:

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
0 голосов
/ 07 марта 2011

в этом цикле parent == Children[i] и Children является геттером для children

Вы действительно хотите добавить один и тот же узел к children и parent, что сделало бы то же самое?узел брат parent в дополнение к ребенку?Я не совсем понимаю, что вы действительно пытаетесь сделать, но это кажется неправильным:

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

edit

Из кода поддержки, который вы опубликовали, проблема можетбыть связанным с тем, как вы создаете объекты:

/* 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);

Похоже, вы создаете новый GeneNode несколько раз, используя один из двух экземпляров Gene в своем конструкторе.Предполагая, что ваш GeneNode сохраняет его как значение свойства, каждый GeneNode будет ссылаться на один и тот же экземпляр Gene (ну, один из двух, funcGene или termGene).Я предполагаю, что это то, что вы имеете в виду, когда говорите новый элемент того же типа, что и предыдущие элементы в ArrayList, этот новый элемент перезаписывает отдельные свойства предыдущих элементов. Любые изменения свойства Gene, назначенного изконструктор в любом узле того же типа будет ссылаться на тот же Gene.Даже если вы создаете новые GeneNodes, они построены из одного и того же Gene.

. При условии, что GeneNode.Value ссылается на Gene, с которым он был создан, могут быть возвращены только два различных значения(соответствует текущему значению одного из двух Gene экземпляров) любым узлом в любой данный момент времени.

Возможно, вы хотите переместить код, чтобы создать новый Gene внутри вашегоцикл. * * 1 043

...