Skip to main content
 首页 » 编程设计

c#之List> 集合成员在不应该更改时更改

2024年02月03日29bonelee

我在控制台项目的主要方法中填充了一个列表。我将此人口传递给一种方法,该方法旨在获取人口中的两个成员并以某种方式分解和重新组合它们以创建两个新的独特成员,这些成员稍后将被添加到人口中。

然而,当我操纵两个原始成员来创建两个新的唯一成员时,两个原始成员在初始种群中发生变化(因此改变了初始种群)。这意味着当我去添加新成员时,我得到了重复列表中的条目。

我没有做任何过于复杂的事情,我认为我只是在做一些愚蠢的事情。

有人知道为什么会这样吗?

这里是被调用来选择最初的两个人口成员的方法:

public static List<Chromosome<Gene>> runEpoch(Random rand, List<Chromosome<Gene>> population, SelectionMethod selectionMethod) 
    { 
        int populationSize = population.Count; 
        int selectionCount = (int)Math.Truncate((population.Count * 0.75)); 
 
        if (selectionMethod == SelectionMethod.Tournament) 
        { 
            for (int i = 0; i < selectionCount; i++) 
            { 
                Chromosome<Gene> parent = selection.runTournament(rand, population); 
                Chromosome<Gene> parentTwo = selection.runTournament(rand, population); 
 
                //Checks for the presence of incestuous mating. In some cases incestuous mating causes a stack overflow to occur that the program can not recover from  
                if (parent != parentTwo) 
                { 
                    //where runGeneOperators calls the crossOver method directly 
                    offSpring = runGeneOperators(rand, parent, parentTwo); 
                } 
                else 
                { 
                    i--; 
                } 
            } 
        } 
        else 
        { 
            //NSGAII 
        } 
        //fixPopulation is meant to sort and remove any excess members 
        return fixPopulation(rand, population, selectionMethod, populationSize); ; 
    } 

下面是创建两个新的唯一成员的代码:

public List<Chromosome<Gene>> crossOver(Random rand, Chromosome<Gene> parentOne, Chromosome<Gene> parentTwo) 
    { 
        List<Chromosome<Gene>> offSpring = new List<Chromosome<Gene>>(); 
 
        int crossPtOne = rand.Next(0, parentOne.Length); 
        int crossPtTwo = rand.Next(0, parentTwo.Length); 
 
        if ((crossPtOne == 0) && (crossPtTwo == 0)) 
        { 
            offSpring.Add(parentOne); 
            offSpring.Add(parentTwo); 
 
            return offSpring; 
        } 
        else 
        { 
            GeneNode<Gene> fragOne = parentOne.Children[crossPtOne]; 
            GeneNode<Gene> fragTwo = parentTwo.Children[crossPtTwo]; 
 
            crossOverPoint = crossPtOne; 
            GeneNode<Gene> genotype = performCrossOver(parentOne.Genotype, fragTwo); 
            success = false; 
 
            parentOne.repair(genotype); 
 
            offSpring.Add(parentOne); 
 
            crossOverPoint = crossPtTwo; 
 
            GeneNode<Gene> genotype2 = performCrossOver(parentTwo.Genotype, fragOne); 
            success = false; 
 
            parentTwo.repair(genotype2); 
 
            offSpring.Add(parentTwo); 
        } 
 
        return offSpring; 
    } 
 
    private GeneNode<Gene> performCrossOver(GeneNode<Gene> tree, GeneNode<Gene> frag) 
    { 
        if (tree != null) 
        { 
            if (crossOverPoint > 0) 
            { 
                if (!success && tree.Left != null) 
                { 
                    crossOverPoint--; 
                    tree.Children[0] = performCrossOver(tree.Left, frag); 
                } 
            } 
 
            if (crossOverPoint > 0) 
            { 
                if (!success && tree.Right != null) 
                { 
                    crossOverPoint--; 
                    tree.Children[1] = performCrossOver(tree.Right, frag); 
                } 
            } 
        } 
 
        if (!success) 
        { 
            if (crossOverPoint == 0) 
            { 
                success = true; 
                return frag; 
            } 
        } 
 
        return tree; 
    } 

请您参考如下方法:

在 C# 中,对象是引用类型,这意味着向集合中添加某些内容只会添加引用。如果您使用相同的引用(在您的情况下为“原始”对象)操作变量,则指向该对象的所有引用也将被更改。您需要以某种方式复制对象以获得不同的对象并对其进行操作。