对象的深层复制

时间:2019-12-21 09:18:31

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

2 个答案:

答案 0 :(得分:0)

不,它不是DeepCopy,要了解发生了什么,请尝试在您的代码之后添加此代码

    // Onclicking the icon
    jump_btn.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            dialog_jump = new Dialog(MainActivity.this);
            // Hide the box's title
            dialog_jump.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog_jump.setContentView(R.layout.jump_dialog);
            // Call jumpButtons method
            jumpButtons();
            // Close btn key
            Button close = dialog_jump.findViewById(R.id.close_btn);
            close.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // dismiss it
                        dialog_jump.dismiss();
                    }
                });
            // Initialize the dialog
            dialog_jump.show();
            // Allow to be cancelled
            dialog_jump.setCancelable(true);
            // Set Animation
            dialog_jump.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id 
            // Make the background of the dialog
            dialog_jump.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        }
    });

结果:

personNew.name = "Steve";
personNew.city.name = "Paris";

// Print out the values of the original person
Console.WriteLine($"{person.name}\t\n{person.city.name}");

因此,您在newPerson中更改了城市名称,但这也会亲自影响该城市。发生这种情况是因为它们是City类的相同实例。这就是MemberwiseClone所做的。它复制字段值,但不创建新的对象实例。对于引用类型,字段值是对对象实例的引用,而不是实例本身。

如果要执行DeepCopy,则需要先将[Serializable]属性添加到类中

John  
Paris

,然后将Clone方法更改为

[Serializable]
class Person
....
[Serializable]
class City

您可以在此答案中找到有关DeepCopy方法的更好示例:

Deep cloning objects

答案 1 :(得分:0)

您刚刚用浅拷贝复制了,是的。 当然,它会复制person实例的所有属性。为什么您认为city是一个例外并且不被复制? 如果您想执行深复制,请尝试以下操作:

人员班级:

    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();
相关问题