C#ArrayList.Add()在add上覆盖以前的对象

时间:2011-03-07 12:37:57

标签: c# c#-4.0 c#-3.0

我编写了一个简单的方法,它接收一个Generic,我希望使用ArrayList.Add()方法将其放入ArrayList中。但是我发现当我去添加一个与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 个答案:

答案 0 :(得分:1)

将代码添加到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

答案 1 :(得分:1)

对于这种关系,你真的应该编写接口。例如

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

如果上述内容正确,那么您可以重载Assignment运算符以传递您希望传递的值。

这也可能对您有用。

C# - Multiple generic types in one list

答案 2 :(得分:0)

此循环中的

parent == Children[i]Childrenchildren的吸气剂

您是否真的想将同一节点添加到childrenparent,除了孩子之外,这会使同一节点成为parent的兄弟节点?我不清楚你真正想要做什么,但这似乎是错误的:

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

修改

根据您发布的支持代码,问题可能与您创建对象的方式有关:

/* 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或{ {1}})。我猜这是你的意思当你说新项目与ArrayList中的前一项相同时,这个新项目会覆盖以前的项目各个属性。termGene的任何更改从相同类型的任何节点中的构造函数分配的属性将引用相同的Gene。即使您要创建新的Gene,它们也是使用相同的GeneNodes构建的。

假设Gene引用它所构造的GeneNode.Value,则只能返回两个不同的值(对应于两个Gene个实例之一的当前值)任何节点在任何给定的时间点。

您可能希望移动代码以在循环中创建新的Gene