C # copy memberwise clone

C # copy memberwise clone

Endless learning and excellence
Ten years east of the river, ten years west of the river, don't bully the young poor
Education represents your past, ability represents your present, and study represents your future
Recently, I read the big talk design pattern: prototype pattern, which is mainly realized by C# deep and shallow replication! You can refer to the deep and shallow copy https://docs.microsoft.com/zh-cn/dotnet/api/system.object.memberwiseclone?redirectedfrom=MSDN&view=net-5.0#System_Object_MemberwiseClone
The so-called deep and shallow replication can be interpreted as:
Shallow copy: calling MemberwiseClone() in C# is shallow copy. If the field is of value type, the field is copied bit by bit. If the field is of reference type, the reference of the object is copied instead of the object. Therefore, the original object and its copy reference the same object!

Deep copy: if the field is of value type, copy the field bit by bit. If the field is of reference type, point the object of reference type to a new object!

The above explanation may not be understood. We make the following cases for analysis:

class Program
    {
        public static void Main()
        {
            //Create P1 object
            Person p1 = new Person();
            p1.Age = 42;
            p1.Name = "Sam";
            p1.IdInfo = new IdInfo("081309207");

            //P2 object obtained by shallow copy
            Person p2 = p1.ShallowCopy();
            //Output separately
            Console.WriteLine("object P1 Related properties are as follows");
            DisplayValues(p1);
            //p1.Name = "";
            //p1.IdInfo.IdNumber = "XXXXX";
            Console.WriteLine("object P2 Related properties are as follows");
            DisplayValues(p2);

            //Now test the deep copy
            Person p3 = p1.DeepCopy();
          
            p1.Name = "George";
            p1.Age = 39;
            p1.IdInfo.IdNumber = "081309208";
            Console.WriteLine("object P1 Related properties are as follows");
            DisplayValues(p1);
            //p1.IdInfo.IdNumber = "CCCCCCC";
            Console.WriteLine("object P3 Related properties are as follows");
            DisplayValues(p3);
            Console.Read();
        }

        public static void DisplayValues(Person p)
        {
            Console.WriteLine("      Name: {0:s}, Age: {1:d}", p.Name, p.Age);
            Console.WriteLine("      Value: {0:d}", p.IdInfo.IdNumber);
        }
    }

    public class IdInfo
    {
        public string IdNumber;

        public IdInfo(string IdNumber)
        {
            this.IdNumber = IdNumber;
        }
    }

    public class Person
    {
        public int Age;
        public string Name;
        public IdInfo IdInfo;

        public Person ShallowCopy()
        {
            return (Person)this.MemberwiseClone();
        }

        public Person DeepCopy()
        {
            Person other = (Person)this.MemberwiseClone();
            other.IdInfo = new IdInfo(IdInfo.IdNumber);
            other.Name = String.Copy(Name);
            return other;
        }
    }

The above code analysis is as follows:

For the original object P1, the object P2 is obtained by shallow replication and P3 is obtained by deep replication

The value type attributes in the original object P1 are Age and Name, and the reference type objects are IdInfo

According to the above concept of shallow replication, Age and Name in P2 are brand-new relative to P1, but IdInfo in P2 and IdInfo in P1 are the same object, and they share the same memory address!

According to the above concept of deep replication, Age and Name in P3 are brand-new relative to P1, but IdInfo in P3 and IdInfo in P1 are not the same object, that is to say, IdInfo in P3 is a brand-new object and has its own memory address!

The above code tests are as follows:

We will now modify the code as follows:

public static void Main()
        {
            //Create P1 object
            Person p1 = new Person();
            p1.Age = 42;
            p1.Name = "Sam";
            p1.IdInfo = new IdInfo("081309207");

            //P2 object obtained by shallow copy
            Person p2 = p1.ShallowCopy();
            //Output separately
            Console.WriteLine("object P1 Related properties are as follows");
            DisplayValues(p1);
            p1.Name = "In shallow copy, modified P1 of Name Property, but Name Is a value type, so it will not affect P2";
            p1.IdInfo.IdNumber = "In shallow copy, modified P1 of IdInfo Property, but IdInfo Is a reference type, so it will affect P2 (Reference type in shallow copy (original object and copy point to the same memory address)";
            Console.WriteLine("object P2 The relevant attributes are as follows");
            DisplayValues(p2);

            Console.Read();
        }

Before outputting P2, we modified the value type Name and reference type IdInfo of P1 object.

Whether shallow or deep replication, the value types in the replica are brand new!

In shallow copy, the reference types of the original object and the copy point to the same memory address. Therefore, modifying the IdInfo of P1 will affect the IdInfo of P2 at the same time

The output is as follows:

Continue to modify the code as follows:

public static void Main()
        {
            //Create P1 object
            Person p1 = new Person();
            p1.Age = 42;
            p1.Name = "Sam";
            p1.IdInfo = new IdInfo("081309207");


            //Now test the deep copy
            Person p3 = p1.DeepCopy();

            p1.Name = "George";
            p1.Age = 39;
            p1.IdInfo.IdNumber = "081309208";
            Console.WriteLine("object P1 Related properties are as follows");
            DisplayValues(p1);
            p1.IdInfo.IdNumber = "Deep copy, modified P1 of IdInfo Properties, even if IdInfo Is a reference type and does not affect P3 (Reference type in deep copy (original object and copy point to different memory addresses respectively)";
            Console.WriteLine("object P3 Related properties are as follows");
            DisplayValues(p3);
            Console.Read();
        }

In deep copy, the reference types of the original object and the copy point to their respective addresses. They are completely different objects!

Therefore: modifying P1 will not affect P3

so, isn't it very simple, isn't it very Easy

Deep and shallow replication is mainly used to create an object that consumes too many resources. Replication can be used to improve efficiency!

The original words of the big talk design pattern are as follows: when you create an object, you need to execute a constructor every time. If the execution time of the constructor is very long, the execution efficiency of the program will be greatly reduced when you create an object many times. Therefore, generally, cloning is the best method on the premise that the initialization information does not change, which hides the creation details of the object, And greatly improve the performance!

Of course, if each class has to write its own deep copy, isn't it very troublesome? Therefore, there is a general deep copy method, as follows:

/// <summary>
    ///General deep replication method
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Serializable]
    public class BaseClone<T>
    {
        public virtual T Clone()
        {
            MemoryStream memoryStream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memoryStream, this);
            memoryStream.Position = 0;
            return (T)formatter.Deserialize(memoryStream);

        }
    }

The relevant cases are as follows (when using the general deep copy method, the Serializable identifier must be added to the relevant class and the reference type of the class: [Serializable]):

class Program 
    {
        public static void Main()
        {
            //Create P1 object
            Person p1 = new Person();
            p1.Age = 42;
            p1.Name = "Sam";
            p1.IdInfo = new IdInfo("081309207");


            //Now test the deep copy
            Person p3 = p1.Clone();

            p1.Name = "George";
            p1.Age = 39;
            p1.IdInfo.IdNumber = "081309208";
            Console.WriteLine("object P1 Related properties are as follows");
            DisplayValues(p1);
            p1.IdInfo.IdNumber = "Deep copy, modified P1 of IdInfo Properties, even if IdInfo Is a reference type and does not affect P3 (Reference type in deep copy (original object and copy point to different memory addresses respectively)";
            Console.WriteLine("object P3 Related properties are as follows");
            DisplayValues(p3);
            Console.Read();
        }

        public static void DisplayValues(Person p)
        {
            Console.WriteLine("      Name: {0:s}, Age: {1:d}", p.Name, p.Age);
            Console.WriteLine("      Value: {0:d}", p.IdInfo.IdNumber);
        }

     
    }

   [Serializable]
    public class IdInfo
    {
        public string IdNumber;

        public IdInfo(string IdNumber)
        {
            this.IdNumber = IdNumber;
        }
    }

   [Serializable]
    public class Person : BaseClone<Person>
    {
        public int Age;
        public string Name;
      
        public IdInfo IdInfo;

        public Person ShallowCopy()
        {
            return (Person)this.MemberwiseClone();
        }

        public Person DeepCopy()
        {
            Person other = (Person)this.MemberwiseClone();
            other.IdInfo = new IdInfo(IdInfo.IdNumber);
            other.Name = String.Copy(Name);
            return other;
        }

        public override Person Clone()
        {
            MemoryStream memoryStream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memoryStream, this);
            memoryStream.Position = 0;
            return (Person)formatter.Deserialize(memoryStream);
        }

    }

    /// <summary>
    ///General deep replication method
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Serializable]
    public class BaseClone<T>
    {
        public virtual T Clone()
        {
            MemoryStream memoryStream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memoryStream, this);
            memoryStream.Position = 0;
            return (T)formatter.Deserialize(memoryStream);

        }
    }

Keywords: Java C# Unity Design Pattern

Added by LiquidEagle on Wed, 26 Jan 2022 02:14:06 +0200