更新类中的对象数组会更新其他对象中的数组

本文关键字:对象 数组 更新 其他 | 更新日期: 2023-09-27 17:56:46

我已经搜索了可能导致意外输出的原因(至少对我来说),但我还没有走得太远。我认为这与类是引用类型有关,但我很困惑,因为您会看到下面的输出显示我预期的字符串,但是数组的内容似乎正在更新引用而不是值?我很困惑。我已经将我的代码简化为以下内容。基本上,我有未知数量的"玩家",还有更多属性,然后我在这里展示。每个"玩家"都有"装备",实际上总是有24件。

我在这里使用了一个数组,因为我希望能够在数组中的同一索引下比较不同玩家的装备。

public class Equipment
{
    public int PropA { get; set; }
    public int PropB { get; set; }
    public Equipment ()
    {
        PropA = 0;
        PropB = 0;
    }
    public Equipment (Equipment eq)
    {
        PropA = eq.PropA;
        PropB = eq.PropB;
    }
}
public class Player
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Equipment[] Equip = new Equipment[2];
    public Player ()
    {
        FirstName = "";
        LastName = "";
        for (int i=0; i<Equip.Length; i++)
        {
            this.Equip[i] = new Equipment();
        }
    }
    public Player (Player p)
    {
        FirstName = p.FirstName;
        LastName = p.LastName;
        for (int i=0; i<p.Equip.Length; i++)
        {
            this.Equip[i] = p.Equip[i];
        }
    }
}
public void LoadPlayers()
{
    Player tmpPlayer = new Player();
    List<Player> PlayerList = new List<Player>();
    tmpPlayer.FirstName = "One";
    tmpPlayer.LastName = "Two";
    tmpPlayer.Equip[0].PropA = 1;
    tmpPlayer.Equip[0].PropB = 2;
    tmpPlayer.Equip[1].PropA = 3;
    tmpPlayer.Equip[1].PropB = 4;
    PlayerList.Add(new Player(tmpPlayer));
    tmpPlayer.FirstName = "Three";
    tmpPlayer.LastName = "Four";
    tmpPlayer.Equip[0].PropA = 5;
    tmpPlayer.Equip[0].PropB = 6;
    tmpPlayer.Equip[1].PropA = 7;
    tmpPlayer.Equip[1].PropB = 8;
    PlayerList.Add(new Player(tmpPlayer));
    foreach (Player p in PlayerList)
    {
        Console.WriteLine(p.FirstName);
        Console.WriteLine(p.LastName);
        Console.WriteLine(p.Equip[0].PropA.ToString());
        Console.WriteLine(p.Equip[0].PropB.ToString());
        Console.WriteLine(p.Equip[1].PropA.ToString());
        Console.WriteLine(p.Equip[1].PropB.ToString());
    }
}

这是我得到的输出:

一二5678三四5678

这是我期望的输出:

一二1234三四5678

除了指出我的错误之外,还有没有明显更好的方法来实现我的目标?

提前感谢您,我感谢任何和所有的帮助!

更新类中的对象数组会更新其他对象中的数组

你需要改变

public Equipment[] Equip = new Equipment[1]; 

否则public Equipment[] Equip = new Equipment[2];你会得到一个IndexOutOfRangeException.

LoadPlayers 方法中,您正在修改相同的Player实例,而不是创建新播放器。因此,您可以获得相同的输出,因为您只有一个实例。创建一个新实例,然后将其添加到您的列表中。

Player tmpPlayer = new Player();
/* set the properties */
PlayerList.Add(new Player(tmpPlayer));
tmpPlayer = new Player();
/* set the properties */
PlayerList.Add(new Player(tmpPlayer));

你应该得到你预期的输出。

嗨,

问题是您只设置了对象的一个实例 tmpPlayer,并且在第二次尝试设置其参数时覆盖了对象中的值。

您可以尝试什么,而不是创建一个对象然后一直更改它并遇到内存参考问题,您可以每次将一个新对象放入数组中,并在添加对象时设置其属性。你应该能够像这样实现它

PlayerList.Add(new Player()
{
    FirstName = "One";
    LastName = "Two";
    Equip[0].PropA = 1;
    Equip[0].PropB = 2;
    Equip[1].PropA = 3;
    Equip[1].PropB = 4;
});
PlayerList.Add(new Player()
{
    FirstName = "Three";
    LastName = "Four";
    Equip[0].PropA = 5;
    Equip[0].PropB = 6;
    Equip[1].PropA = 7;
    Equip[1].PropB = 8;
});

有了这个,每个对象都应该是唯一的,希望你能得到你想要的输出。

问题是您的复制构造函数 public Player (Player p) 将复制播放器的装备分配给新玩家。由于您使用此构造函数来创建您实际放入列表中的两个玩家,因此它们的装备都引用了原始玩家的装备tmpPlayer

您可以通过让复制构造函数执行设备的复制来解决此问题:

public Player (Player p)
{
    FirstName = p.FirstName;
    LastName = p.LastName;
    for (int i=0; i<p.Equip.Length; i++)
    {
        this.Equip[i] = new Equipement(p.Equip[i]);
    }
}