Preface
We have learned the design pattern before, in which we have learned the prototype pattern. This involves cloning your own objects. That is to copy the object. This involves such a concept. What is a deep copy and what is a shallow copy? Let's have a look.
Shallow copy
First let's look at the light copy. Shallow copy is to copy all fields in an object to a new object. Shallow copy has different effects on value type and reference type. When a value of type value is copied to the replica, changing the value in the replica does not affect the value of the original object. However, what the reference type is copied to the replica is the reference of the reference type. Is not a referenced object. In this way, changing the value in the copy will cause the value of the original object to be changed. But we need to exclude the String type when referring to the type.
So why does reference type change the value of the replica, and string type is excluded? First of all, we need to know the concept that string type is an immutable data type, which means that the string object can not be changed after initialization. On the surface, the method and operation of modifying the content of the string is actually to create a new string, and then copy the content of the old string to the new string as needed. How to understand you? Let's look at the following case:
#region string comparison /// <summary> /// Get memory address method of reference type /// </summary> /// <param name="o"></param> /// <returns></returns> public static string getMemory(object o) { GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned); IntPtr addr = h.AddrOfPinnedObject(); return "0x" + addr.ToString("X"); } /// <summary> /// string comparison /// </summary> public static void Compares() { string a = "123"; Console.WriteLine("a Reference address:\t\t" + getMemory(a)); string b = "123"; Console.WriteLine("b Reference address:\t\t" + getMemory(b)); Console.WriteLine("a And b Comparison:\t\t" + Object.ReferenceEquals(a, b)); b = "456"; Console.WriteLine("b Reference address:\t\t" + getMemory(b)); } #endregion
Here we see a = 123, b = 123. We see that their reference addresses are the same. That is to say, when we first create a, we create string a and have a reference address. Then when we create b, we first look for the same value. If the same value exists, get its reference address. That's why the reference addresses of a and b are the same. This involves something called character resident pool. The string is saved. Then we modify the value of b and output its reference address, which is different from the previous reference address. The description is not to modify the original value, but to recreate a string and retrieve its reference address.
Let's look at a shallow copy case. First, we prepare the values of the following data types: int, string, enum, struct, class, int [], string [].
/// <summary> /// enumeration /// </summary> public enum EnumTest { TestOne = 1, TestTwo = 2 } /// <summary> /// structural morphology /// </summary> public struct StructTest { public int Test; public StructTest(int i) { Test = i; } } /// <summary> /// class /// </summary> public class ClassTest { public string TestString; public ClassTest(string _string) { TestString = _string; } } /// <summary> /// Deep copy /// </summary> public class DeepClone : ICloneable { public int _int = 1; public string _string = "1"; public EnumTest _enum = EnumTest.TestOne; public StructTest _struct = new StructTest(1); public ClassTest _class = new ClassTest("1"); public int[] arrInt = new int[] { 1 }; public string[] arrString = new string[] { "1" }; public object Clone() { var NewOne = JsonConvert.SerializeObject(this); return JsonConvert.DeserializeObject<DeepClone>(NewOne); } } class Program { static void Main(string[] args) { DeepClone simple = new DeepClone(); var simpleTwo = (DeepClone)simple.Clone(); simpleTwo._int = 2; simpleTwo._string = "2"; simpleTwo._enum = EnumTest.TestTwo; simpleTwo._struct.Test = 2; simpleTwo._class.TestString = "2"; simpleTwo.arrInt[0] = 2; simpleTwo.arrString[0] = "2"; Console.WriteLine($"int Type change Original object:{simple._int}\t\t Backup object:{simpleTwo._int}"); Console.WriteLine($"string Type change original object:{simple._string}\t\t Backup object:{simpleTwo._string}"); Console.WriteLine($"enum Type change Original object:{(int)simple._enum}\t\t Backup object:{(int)simpleTwo._enum}"); Console.WriteLine($"struct Type change original object:{simple._struct.Test}\t\t Backup object:{simpleTwo._struct.Test}"); Console.WriteLine($"class Type change original object:{simple._class.TestString}\t\t Backup object:{simpleTwo._class.TestString}"); Console.WriteLine($"int Array type changes the original object:{simple.arrInt[0]}\t\t Backup object:{simpleTwo.arrInt[0]}"); Console.WriteLine($"string Array type changes the original object:{simple.arrString[0]}\t\t Backup object:{simpleTwo.arrString[0]}"); } }
We make shallow copies of these types by inheriting the ICloneable interface and then modify the copy object. Output the original object and the copy object for comparison. We found that the original object values of int,enum,struct, value type and string, the special reference type, were not changed. But class,int[],string [], the original object of reference type object has been affected to change the value. It also verifies what we said before. Shallow copy is to assign an object to a copy object. The value type copies the value, and the reference type copies its reference object. Modify the value of the replica object, the value type and the original string object will not be affected, and the reference type will be affected except for the original string object.
Deep copy
We have seen the shallow copy above. The shallow copy still has some influence. If it is not handled properly, it may become a bug. So let's see what the corresponding deep copy looks like? It can be declared that the deep copy does not discriminate between value type and reference type. Deep copy also copies all fields in the object to the new object, but the object will be recreated and then copied to the replica object, regardless of value type or reference type. Changes to the replica object will not affect the original object, regardless of type.
Let's continue to make a deep copy of the above example:
/// <summary> /// Deep copy /// </summary> public class DeepClone : ICloneable { public int _int = 1; public string _string = "1"; public EnumTest _enum = EnumTest.TestOne; public StructTest _struct = new StructTest(1); public ClassTest _class = new ClassTest("1"); public int[] arrInt = new int[] { 1 }; public string[] arrString = new string[] { "1" }; public object Clone() { var NewOne = JsonConvert.SerializeObject(this); return JsonConvert.DeserializeObject<DeepClone>(NewOne); } } class Program { static void Main(string[] args) { DeepClone simple = new DeepClone(); var simpleTwo = (DeepClone)simple.Clone(); simpleTwo._int = 2; simpleTwo._string = "2"; simpleTwo._enum = EnumTest.TestTwo; simpleTwo._struct.Test = 2; simpleTwo._class.TestString = "2"; simpleTwo.arrInt[0] = 2; simpleTwo.arrString[0] = "2"; Console.WriteLine($"int Type change Original object:{simple._int}\t\t Backup object:{simpleTwo._int}"); Console.WriteLine($"string Type change original object:{simple._string}\t\t Backup object:{simpleTwo._string}"); Console.WriteLine($"enum Type change Original object:{(int)simple._enum}\t\t Backup object:{(int)simpleTwo._enum}"); Console.WriteLine($"struct Type change original object:{simple._struct.Test}\t\t Backup object:{simpleTwo._struct.Test}"); Console.WriteLine($"class Type change original object:{simple._class.TestString}\t\t Backup object:{simpleTwo._class.TestString}"); Console.WriteLine($"int Array type changes the original object:{simple.arrInt[0]}\t\t Backup object:{simpleTwo.arrInt[0]}"); Console.WriteLine($"string Array type changes the original object:{simple.arrString[0]}\t\t Backup object:{simpleTwo.arrString[0]}"); } }
Here we see the running result. No matter the value type or the reference type, the value of the original object will not be affected after the replica object is modified. This is the characteristic of deep copy.
summary
We've seen the shallow copy and the deep copy. Let's review them carefully. Shallow copy copies the fields of the object to the new object, but when modifying the new object, the fields of value type and string type will not affect the fields of the original object, and the reference type will affect the values of the original object except for string type. Deep copy also copies the field of the object to the new object, but the change of value type or reference type will not affect the value of the original object. Because the deep copy is to recreate the original object and then copy it to the replica object.
Life is only beautiful, not brilliant.
Welcome to scan the QR code below and learn more with me