将一个对象添加到多个数组并保持每个副本之间的差异?
Add one object to multiple arrays and keep differences between each copy?
基本上,我想创建一个对象,然后将该对象添加到一堆不同的数组中,并确保如果一个数组更改对象的值,则其他数组中的其他对象不会更改它们的值.
例如,假设我声明一把枪有 50 颗子弹存储在一个整数中:
Gun tommygun = new Gun(50);
我有两个士兵,每个人都有一个枪支清单,并为每个人添加一把冲锋枪。
Soldier1.Guns.Add(tommygun);
Soldier2.Guns.Add(tommygun);
士兵 1 开枪:
Soldier1.Shoot(Soldier1.Guns[0]);
这会使 Soldier1 的弹药减少 1。现在是 49。这是否也会减少 Soldier2 的枪的弹药?如果是这样,我如何在不为每个士兵创建单独的冲锋枪的情况下避免这种情况?
为每个士兵创建一个单独的冲锋枪对象实例。
由于对象是通过引用传递的,此时您正在两个士兵之间共用一把枪。
看来您是 OOP 新手
您可以通过 2 种方法
- 创建新的枪支实例
- 创建一把Clone的枪
您需要执行深拷贝。否则,您的 Gun 对象就是别名。
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Gun g1 = new Gun(50);
g1.addModification("Scope");
Gun g2 = (Gun) g1.Clone();
if (g1 != g2)
Console.WriteLine("These objects are not aliases");
Console.WriteLine(g1);
Console.WriteLine(g2);
Console.ReadLine();
}
}
class Gun : ICloneable
{
int bullets;
List<object> modifications;
public Gun(int bullets)
{
this.bullets = bullets;
modifications = new List<object>();
}
public void addModification(object o)
{
modifications.Add(o);
}
public override string ToString()
{
return "Bullets: " + bullets + " Modifications: " + modifications[0];
}
public object Clone()
{
Gun clone = new Gun(this.bullets);
foreach (object o in this.modifications)
clone.modifications.Add(o);
return clone;
}
}
}
另一种选择是在 Gun
class 上实施 Clone
方法。您可以使用 MemeberwiseClone
创建浅表副本,如果需要,您可以为 Gun
可能具有的任何引用类型属性创建新项。
例如:
public class Gun
{
public int MaxRounds { get; set; }
public List<Bullet> Ammunition { get; set; } = new List<Bullet>();
public Gun(int maxRounds)
{
MaxRounds = maxRounds;
}
public Gun Clone()
{
// Create a shallow copy of all the properties
Gun newGun = MemberwiseClone() as Gun;
// Because 'Bullet' is a reference type, we need to make a deep copy of 'Ammunition'
newGun.Ammunition = Ammunition.Select(bullet => bullet.Clone()).ToList();
return newGun;
}
}
public class Bullet
{
public int Damage { get; set; }
public int Range { get; set; }
public Bullet Clone()
{
return MemberwiseClone() as Bullet;
}
}
然后你可以这样做:
Soldier1.Guns.Add(tommygun.Clone());
Soldier2.Guns.Add(tommygun.Clone());
基本上,我想创建一个对象,然后将该对象添加到一堆不同的数组中,并确保如果一个数组更改对象的值,则其他数组中的其他对象不会更改它们的值.
例如,假设我声明一把枪有 50 颗子弹存储在一个整数中:
Gun tommygun = new Gun(50);
我有两个士兵,每个人都有一个枪支清单,并为每个人添加一把冲锋枪。
Soldier1.Guns.Add(tommygun);
Soldier2.Guns.Add(tommygun);
士兵 1 开枪:
Soldier1.Shoot(Soldier1.Guns[0]);
这会使 Soldier1 的弹药减少 1。现在是 49。这是否也会减少 Soldier2 的枪的弹药?如果是这样,我如何在不为每个士兵创建单独的冲锋枪的情况下避免这种情况?
为每个士兵创建一个单独的冲锋枪对象实例。
由于对象是通过引用传递的,此时您正在两个士兵之间共用一把枪。
看来您是 OOP 新手
您可以通过 2 种方法
- 创建新的枪支实例
- 创建一把Clone的枪
您需要执行深拷贝。否则,您的 Gun 对象就是别名。
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Gun g1 = new Gun(50);
g1.addModification("Scope");
Gun g2 = (Gun) g1.Clone();
if (g1 != g2)
Console.WriteLine("These objects are not aliases");
Console.WriteLine(g1);
Console.WriteLine(g2);
Console.ReadLine();
}
}
class Gun : ICloneable
{
int bullets;
List<object> modifications;
public Gun(int bullets)
{
this.bullets = bullets;
modifications = new List<object>();
}
public void addModification(object o)
{
modifications.Add(o);
}
public override string ToString()
{
return "Bullets: " + bullets + " Modifications: " + modifications[0];
}
public object Clone()
{
Gun clone = new Gun(this.bullets);
foreach (object o in this.modifications)
clone.modifications.Add(o);
return clone;
}
}
}
另一种选择是在 Gun
class 上实施 Clone
方法。您可以使用 MemeberwiseClone
创建浅表副本,如果需要,您可以为 Gun
可能具有的任何引用类型属性创建新项。
例如:
public class Gun
{
public int MaxRounds { get; set; }
public List<Bullet> Ammunition { get; set; } = new List<Bullet>();
public Gun(int maxRounds)
{
MaxRounds = maxRounds;
}
public Gun Clone()
{
// Create a shallow copy of all the properties
Gun newGun = MemberwiseClone() as Gun;
// Because 'Bullet' is a reference type, we need to make a deep copy of 'Ammunition'
newGun.Ammunition = Ammunition.Select(bullet => bullet.Clone()).ToList();
return newGun;
}
}
public class Bullet
{
public int Damage { get; set; }
public int Range { get; set; }
public Bullet Clone()
{
return MemberwiseClone() as Bullet;
}
}
然后你可以这样做:
Soldier1.Guns.Add(tommygun.Clone());
Soldier2.Guns.Add(tommygun.Clone());