更新类中的对象数组会更新其他对象中的数组
本文关键字:对象 数组 更新 其他 | 更新日期: 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]);
}
}