c#中的复制构造函数仍然保留其引用

本文关键字:保留 引用 构造函数 复制 | 更新日期: 2023-09-27 18:11:34

我目前正在用Windows Forms和c#编写关卡生成程序。每个关卡都是从一系列"模式"中创建的,这些模式在启动时被加载到数组中。当创建关卡时,程序将从这个数组中随机选择一些模式,随机旋转它们并创建关卡。选择的每个模式都存储在chosenPattern变量中,这样就可以在不修改原始模式的情况下旋转它。

下面是我用来选择图案并旋转它的代码。

int rand = randomNumber(0, patterns.Count - 1);                        
Level chosenPattern = new Level(patterns[rand]);
chosenPattern = rotatePattern(chosenPattern, randomNumber(0, 3));

这里是关卡构造器,包括复制构造器。

public class Level
    {
        public List<List<char>> grid;
        public string solution;
        public int difficulty;
        public TimeSpan generationTime;
        public Level()
        {
            grid = new List<List<char>>();
            solution = "";
            difficulty = 0;
            generationTime = TimeSpan.MinValue;
        }
        public Level(Level level)
        {
            grid = level.grid;
            solution = level.solution;
            difficulty = level.difficulty;
            generationTime = level.generationTime;
        }
    }

然而,即使使用复制构造函数,当旋转存储的模式时,存储在数组中的模式仍然是旋转的,我不确定为什么(注意:我是一个相当新手c#程序员)

和rotatpattern函数:

 public Level rotatePattern(Level pattern, int rotation)
        {
            Level tempPattern = pattern;
            switch (rotation)
            {
                case 1:
                    //Rotate 90 - Reverse Each Row
                    for(int i = 0; i < tempPattern.grid.Count; i++)
                    {
                        tempPattern.grid[i].Reverse();
                    }
                    break;
                case 2:
                    //Rotate 180 - Reverse Each Row, then Each Column
                    for (int i = 0; i < tempPattern.grid.Count; i++)
                    {
                        tempPattern.grid[i].Reverse();
                    }
                    tempPattern.grid.Reverse();
                    break;
                case 3:
                    //Rotate 270 - Reverse Each Column
                    tempPattern.grid.Reverse();
                    break;
            }
            return tempPattern;
        }

c#中的复制构造函数仍然保留其引用

在复制构造函数中,将其替换为

public Level(Level level)
{
     grid = level.grid.Select(x=>x.ToList()).ToList();
     solution = level.solution;
     difficulty = level.difficulty;
     generationTime = level.generationTime;
}

简单地传递List将复制引用而不是值

这是因为grid属性与其他属性不同,不是ValueType,因此复制的是地址而不是实际值。

Copy Constructor只是一个接受相同类型实例的构造函数。如果你赋值给其中一个属性i。e网格,那么如果这个属性不是ValueType,那么你应该做一个方法来复制这些值,与grid = level.grid的普通赋值只是不会削减它,并将产生相同的结果。

尝试更改grid分配为以下内容:

grid = level.grid.Select(lst => lst.ToList()).ToList();