2011-03-07 78 views
0

我已經寫了一個簡單的方法,接收一個通用的,我想放入一個ArrayList使用ArrayList.Add()方法。但是我發現,當我去添加一個與ArrayList中的前一個項目具有相同類型的新項目時,這個新項目將覆蓋以前項目的各個屬性。C#ArrayList.Add()覆蓋以前的對象添加

下面是代碼,它的基本和相當尷尬,我似乎無法糾正這個覆蓋問題。

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

我很確定它是一個簡單的錯誤,但我看了這麼久,我不能看到樹木。任何想法將不勝感激。

非常感謝提前。

Luke

這裏是利用這個類的代碼。

編輯:改寫時發生之後,該方法已經執行其邏輯

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

可能有助於張貼您正在使用這個類,其中的代碼。我想知道你是否只是一直將相同的實例添加到列表中。 – Nick 2011-03-07 12:42:31

+6

爲什麼你使用'ArrayList'給定你可以清楚地使用泛型,不感興趣? – 2011-03-07 12:43:53

+0

您是否想要爲每個孩子添加一份參考指南到根目錄? – smartcaveman 2011-03-07 12:52:36

回答

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 
+0

發佈通過泛型到add方法的附加代碼。 你認爲這是調用'GeneNode geneNode = new GeneNode ();'兩次使用不同的實例化值的結果。 – user648132 2011-03-07 13:03:33

0

在這個循環parent == Children[i]Childrenchildren

一個getter你真的要被添加相同的節點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); 

好像你正在使用其構造函數中的Gene兩個實例之一多次創建一個新的GeneNode。假設您的GeneNode正在將其保存爲屬性值,則每個GeneNode都將引用Gene(以及兩個之一,即funcGenetermGene)的同一個實例。我猜這是你的意思,當你說新項目與ArrayList中的以前的項目相同的類型,這個新項目覆蓋了以前的項目單個屬性。對於同一類型的任何節點中的構造函數分配的Gene屬性的任何更改都將引用相同的Gene。即使您正在創建新的GeneNodes,它們也是由相同的Gene構建的。

所以假設GeneNode.Value引用Gene,它正在與構造,只能有兩個不同的值返回(對應於兩個Gene實例中的一個的電流值)由任何節點在任何給定時間點。

也許您想要移動代碼以在循環中創建新的Gene

+0

父在這種情況下不是另一個ArrayList它只是一個不同的對象。條件只是檢查父母是否有孩子,或者是否已達到其最大子女數量。父母有效地擁有自己的子女ArrayList,其數量不應超過2個。樹的多個孩子可以多於2個。 – user648132 2011-03-07 13:06:22

+0

'parent =(GeneNode )this.Children [i];' - - - 和'Children = {get this.children}' - 所以'children.Add()'創建一個父親的同胞 – 2011-03-07 13:08:54

+0

我很欣賞你在說什麼,但'parent =(GeneNode )this.Children [i]; '從樹中獲取最後一個添加的節點。 'this.children'僅僅是一個容器,用於添加到它不執行的樹和父/子關係的所有節點。所以真正做'children.Add()'只是添加一個新的孩子到我可以直接編入索引的樹的子樹列表中。它不會嚴格製造任何事物的兄弟姐妹。 – user648132 2011-03-07 13:38:44

1

對於這種關係,你應該對接口進行編碼。例如。

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

如果以上是正確的,那麼你可以重載你的Assignment操作符來傳遞你想傳遞的值。

這也許對你有用。

C# - Multiple generic types in one list

+0

對不起,我沒有看到你的意思。你介意進一步解釋一下嗎? – user648132 2011-03-07 13:28:35