Analysis of C # deep copy and shallow copy (rpm)

Original link: http://www.cnblogs.com/xcsn/p/4409615.html
1. deep copy and shallow copy
  I.e. what is often called copy copy (the Copy) or clone (Clone), copy of an object that is a copy "identical" in the new object from an existing object out. Although the objects are copied, but different methods of copy, copy out the new object is not entirely the same, there are some differences inside the object. There are two usual copies, that deep copy and shallow copy, then what is the difference between the two it? MSDN there IClone Clone method to interface this description: In a deep copy, all objects are duplicated; in a shallow copy, only the top-level object is repeated, and the top-level object contains the following references. As can be seen, between the deep and shallow copy copy difference is whether the sub-object replication. This is how to understand it? Now I come to verify the difference between the two through code with child objects.
First, the definition of two types: Student and ClassRoom, wherein Student type contains ClassRoom, respectively, and these two types of deep copy implement custom interfaces (IDeepCopy) and shallow copy Interface (IShallowCopy).
FIG class as follows:

Code is defined as follows:

 

/// <summary>
    /// 深拷贝接口
    /// </summary>
    interface IDeepCopy
    {
        object DeepCopy();
    }

    /// <summary>
    /// 浅拷贝接口
    /// </summary>
    interface IShallowCopy
    {
        object ShallowCopy();
    }

    /// <summary>
    /// 教室信息
    /// </summary>
    class ClassRoom : IDeepCopy, IShallowCopy
    {
        public int RoomID = 1;
        public string RoomName = "Room1";

        public override string ToString()
        {
            return "RoomID=" + RoomID + "\tRoomName=" + RoomName;
        }
        public object DeepCopy()
        {
            ClassRoom r = new ClassRoom();
            r.RoomID = this.RoomID;
            r.RoomName = this.RoomName;
            return r;
        }
        public objectShallowCopy () 
        { 
            // return directly using the built-in shallow copy method 
            return  the this .MemberwiseClone (); 
        } 
    } 

    class Student: IDeepCopy, IShallowCopy 
    { 
        // the sake of simplicity, to use public fields 
        public  String the Name;
         public  int Age;
         // custom type, assume that each has only a Student Classroom 
        public Classroom Room = new new Classroom (); 

        public Student () 
        { 
        } 
        public Student ( String name, int Age) 
        { 
            the this.Name = name;
            this.Age = age;
        }
        public object DeepCopy()
        {
            Student s = new Student();
            s.Name = this.Name;
            s.Age = this.Age;
            s.Room = (ClassRoom)this.Room.DeepCopy();
            return s;
        }
        public object ShallowCopy()
        {
            return this.MemberwiseClone();
        }

        public override string ToString()
        {
            return "Name:" + Name + "\tAge:" + Age + "\t" + Room.ToString();
        }

    }pastingpasting

 

Test code:
 
S1 = Student new new Student ( " Vivi " , 28 ); 
Console.WriteLine ( " S1 = [ " + S1 + " ] " ); 
Student S2 = (Student) s1.ShallowCopy (); 
 // Student S2 = (Student) s1.DeepCopy (); 
Console.WriteLine ( " s2 = [ " + s2 + " ] " ); // where s1 and s2 same content 
Console.WriteLine ( " ------------- ---------------- " ); 
 // content of s2 
s2.Name = "Tianyue " ; 
s2.Age = 25 ; 
s2.Room.RoomID = 2 ; 
s2.Room.RoomName = " Room2 " ; 
Console.WriteLine ( " S1 = [ " + S1 + " ] " ); 
Console.WriteLine ( " S2 = [ " + S2 + " ] " ); 
 // print again to compare two objects 
Console.ReadLine ();

 

operation result:

a.ShallowCopy
= S1, the [Name Configure: Vivi-the Age: 28, RoomID = 1 RoomName = Room1]
galaxy s2 = [Name Configure: Vivi-the Age: 28, RoomID = 1 RoomName = Room1]
------------------ -------------------------------------------
s1=[Name:Vivi   Age:28  RoomID=2        RoomName=Room2]
s2=[Name:tianyue        Age:25  RoomID=2        RoomName=Room2]

b.DeepCopy
s1=[Name:Vivi   Age:28  RoomID=1        RoomName=Room1]
s2=[Name:Vivi   Age:28  RoomID=1        RoomName=Room1]
-----------------------------
s1=[Name:Vivi   Age:28  RoomID=1        RoomName=Room1]
s2=[Name:tianyue        Age:25  RoomID=2        RoomName=Room2]
As can be seen from the above results, when two objects are completely deep copy "separation", wherein a change does not affect the other objects;
When two objects are not completely shallow copy of "separation", change the content of top-level object will not have an impact on another object, but change the contents of the child object, the two objects at the same time be changed.
This difference, i.e., a copy pointer memory or copy copy sub-object depends. Deep copy of the child object reallocate some memory space, and to copy the contents therein;
Shallow copy only the original pointer to the child object.
Diagram is as follows:
2. shallow copy and assignment
Most of assignment Object-oriented languages ​​are passing references, that is, to change the address of the object pointer, but does not copy the memory, nor do any copy operation.
It can be seen, the difference between a shallow copy of the assignment is to copy the top-level object or not. Of course, there are some exceptions, such as the type definition overloaded assignment operator (assignment operator),
Or some type of agreement passed by value, as in C # structures and enumerated types.
Assignment diagram is as follows:
3.C ++ copy constructor
与其它面向对象语言不同,C++允许用户选择自定义对象的传递方式:值传递和引用传递。在值传递时就要使用对象拷贝,比如说按值传递参数,编译 器需要拷贝一个对象以避免原对象在函数体内被破坏。为此,C++提供了拷贝构造函数用来实现这种拷贝行为,拷贝构造函数是一种特殊的构造函数,用来完成一 些基于同一类的其它对象的构造和初始化。它唯一的参数是引用类型的,而且不可改变,通常的定义为X(const X&)。在拷贝构造函数里,用户可以定义对象的拷贝行为是深拷贝还是浅拷贝,如果用户没有实现自己的拷贝构造函数,那么编译器会提供一个默认实 现,该实现使用的是按位拷贝(bitwise copy),也即本文所说的浅拷贝。构造函数何时被调用呢?通常以下三种情况需要拷贝对象,此时拷贝构造函数将会被调用。
1.一个对象以值传递的方式传入函数体
2.一个对象以值传递的方式从函数返回
3.一个对象需要通过另外一个对象进行初始化
4.C# MemberwiseClone与ICloneable接口
和C++里的拷贝构造函数一样,C#也为每个对象提供了浅拷贝的默认实现,不过C#里没有拷贝构造函数,而是通过顶级类型Object里的 MemberwiseClone方法。MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。有没有默认的深拷贝实现呢?当然是没有,因为需要所有参与拷贝 的对象定义自己的深拷贝行为。C++里需要用户实现拷贝构造函数,重写默认的浅拷贝;C#则不同,C#(确切的说是.NET Framework,而非C#语言)提供了ICloneable 接口,包含一个成员 Clone,它用于支持除 MemberwiseClone 所提供的克隆之外的克隆。C++通过拷贝构造函数无法确定子对象实现的是深拷贝还是浅拷贝,而C#在“强制”实现浅拷贝的基础上,提供 ICloneable 接口由用户定义深拷贝行为,通过接口来强制约束所有参与拷贝的对象,个人觉得,这也算是一小点C#对C++的改进。
 
5.深拷贝策略与实现
深拷贝的要点就是确保所有参与拷贝的对象都要提供自己的深拷贝实现,不管是C++拷贝构造函数还是C#的ICloneable 接口,事实上都是一种拷贝的约定。有了事先的约定,才能约束实现上的统一,所以关键在于设计。
但偶尔也会在后期才想到要深拷贝,怎么办?总不能修改所有之前的实现吧。有没有办法能够通过顶级类而不关心内部的子对象直接进行深拷贝呢?能不 能搞个万能的深拷贝方法,在想用的时候立即用,而不考虑前期的设计。这样“大包大揽”的方法,难点在于实现时必须自动获取子对象的信息,分别为子对象实现 深拷贝。C++里比较困难,.NET的反射机制使得实现容易一些。不过这样的方法虽然通用,实则破坏了封装,也不符合“每个类对自己负责”的设计原则。
 
基于.NET的反射机制,以前写了一个通用的序列化方法,现在可以拿过来,先序列化,然后再反序列化回来,也即是一个深拷贝,示例代码如下:
深拷贝示例代码:
 

 

#region ICloneable Members

        /// <summary>
        /// 此处的复制为深拷贝,在实现上,为了简化,采用序列化和反序列化。
        /// </summary>
        /// <returns>深拷贝对象</returns>
        public object Clone()
        {
            Student stu = new Student();
            XmlStorageHelper helper = new XmlStorageHelper();
            string strXml = helper.ConvertToString(this);
            helper.LoadFromString(stu, strXml);   //从XML字符串来赋值

            return stu;
        }

        #endregion

转自:http://www.cnblogs.com/nliao/archive/2012/11/18/2776114.html

转载于:https://www.cnblogs.com/xcsn/p/4409615.html

Guess you like

Origin blog.csdn.net/weixin_30363509/article/details/94793313