Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对象的深度复制_C#_Deep Copy_Shallow Copy - Fatal编程技术网

C# 对象的深度复制

C# 对象的深度复制,c#,deep-copy,shallow-copy,C#,Deep Copy,Shallow Copy,我有两节课。在一个类中嵌套了另一个类 class Person : ICloneable { public string name; public City city; public object Clone() { return this.MemberwiseClone(); } } class City { public string name; public City( string _n) {

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

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;
    }
}
在Person类中,使用克隆方法进行浅层复制。 当我制作类人克隆时,我得到了类人克隆和嵌套类城市克隆

        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类的浅拷贝,但它看起来像深拷贝。为什么?

不,它不是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
然后将克隆方法更改为

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方法示例:


您刚刚用浅拷贝进行了拷贝,这是正确的。 当然,它会复制
person
实例的所有属性。为什么你认为城市是一个例外而不被复制? 如果要执行深度复制,请尝试以下操作:

个人班级:

    class Person : ICloneable
    {
        public string name;
        public City city;

        public object Clone()
        {
            return this.MemberwiseClone();
        }
        public Person DeepCopyAndDisposeCity()
        {
            return new Person()
            {
                name = this.name,
                city = null
            };
        }
    }
节目

            Person person = new Person()
            {
                name = "John",
                city = new City("London")
            };

            Person personNew = person.DeepCopyAndDisposeCity(); //(Person)person.Clone();
            //personNew.city = new City( "Hanoi");
            string cityOfNewPersion= personNew.city == null ? "null" : personNew.city.name;

            Console.WriteLine("Person:");
            Console.WriteLine($"{person.name}\t\n{person.city.name}");
            Console.WriteLine("New Person:");
            Console.WriteLine($"{personNew.name}\t\n{cityOfNewPersion}");
            Console.ReadKey();

仍然有一个
City
对象,您的
Person
对象都引用了同一个对象。深度克隆将导致
城市
对象也被复制。