对象的深层复制

问题描述 投票:0回答:3

我有两节课。在一个嵌套另一个类。

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类的浅表副本,但它看起来像深层副本。为什么呢

c# deep-copy shallow-copy
3个回答
1
投票

[Object.MemberwiseClone复制引用类型字段的引用(但不引用引用的对象),因此您在新的City对象中获得了对同一Person对象的引用。


0
投票

不,它不是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方法的更好示例:

Deep cloning objects


0
投票

您刚刚使用shallow copy

© www.soinside.com 2019 - 2024. All rights reserved.