我有两节课。在一个嵌套另一个类。
class Person : ICloneable
{
public string name;
public City city;
public object Clone()
{
return this.MemberwiseClone();
}
}
class City
{
public string name;
public City( string _n)
{
name = _n;
}
}
In Person类是用于制作浅表副本的克隆方法。当我制作了Person类的克隆时,我得到了Person类的克隆和嵌套的City类的克隆。
Person person = new Person()
{
name = "John",
city = new City("London")
};
Person personNew = (Person)person.Clone();
Console.WriteLine( $"{personNew.name}\t\n{personNew.city.name}");
Result:
John
London
我希望获得City类的值为null,因为我制作了Person类的浅表副本,但它看起来像深层副本。为什么呢
[Object.MemberwiseClone复制引用类型字段的引用(但不引用引用的对象),因此您在新的City
对象中获得了对同一Person
对象的引用。
不,它不是DeepCopy,要了解发生了什么,请尝试在您的代码之后添加此代码
personNew.name = "Steve";
personNew.city.name = "Paris";
// Print out the values of the original person
Console.WriteLine($"{person.name}\t\n{person.city.name}");
结果:
John
Paris
因此您在newPerson中更改了城市名称,但这也会亲自影响该城市。发生这种情况是因为它们是City类的相同实例。这就是MemberwiseClone所做的。它复制字段值,但不创建新的对象实例。对于引用类型,字段值是对对象实例的引用,而不是实例本身。
如果要执行DeepCopy,则需要先将[Serializable]属性添加到类中>
[Serializable] class Person .... [Serializable] class City
然后将Clone方法更改为
public object Clone() { using (MemoryStream stream = new MemoryStream()) { if (this.GetType().IsSerializable) { BinaryFormatter fmt = new BinaryFormatter(); fmt.Serialize(stream, this); stream.Position = 0; return fmt.Deserialize(stream); } return null; } }
您可以在此答案中找到有关DeepCopy方法的更好示例:
您刚刚使用shallow copy