The technique of creating a copy of an object is called a copy (also called a clone). We divide the copy into shallow copy and deep copy.
Shallow copy: Copies all the fields in the object to the new object (copy). Where the value of the value Type field is copied to the copy, the modifications in the copy do not affect the value corresponding to the source object. While a reference type's field is copied to a reference of a reference type, instead of a referenced object, modifying the field value of the reference type in the replica affects the source object itself.
Deep copy: Similarly, all the fields in the object are copied to the new object. However, whether the object's value Type field, or reference Type field, is recreated and assigned a value, modifications to the copy do not affect the source object itself.
Whether it is a shallow copy or a deep copy, Microsoft recommends explicitly telling the caller in a way that the type inherits the ICloneable interface: The type can be copied. Of course, the ICloneable interface only provides a method that is declared as clone, and we can implement a shallow copy or deep copy within the Clone method as required. The implementation code for a simple shallow copy is as follows:
classemployee:icloneable{ Public stringIdcode {Get;Set; } Public intAge {Get;Set; } PublicDepartment Department {Get;Set; } Public ObjectClone () {return This. MemberwiseClone (); }}classdepartment{ Public stringName {Get;Set; } Public Override stringToString () {return This. Name; }}//calledEmployee Mike =Newemployee{Idcode="NB123", Age= -, Department=NewDepartment {Name="Dep1" }}; Employee Rose= Mike. Clone () asEmployee; Console.WriteLine (Mike. Idcode); Console.WriteLine (Mike. Age); Console.WriteLine (Mike. Department); Console.WriteLine ("change Mike's value"); Mike. Idcode="NB456", Mike. Age= -, Mike. Department.name="DEP2"; Console.WriteLine (Rose. Idcode); Console.WriteLine (Rose. Age); Console.WriteLine (Rose. Department);
The output is:
NB123 -Dep1change Mike's valueNB123 -DEP2
Note that the Idcode property of the employee is a string type. The string type is theoretically a reference type, but because of the specificity of the reference type, whether implemented or semantic, the Object.memberwiseclone method still creates a copy of it. That is, in a shallow copy process, we should treat the string as a value type.
The Department property of an employee is a reference type, so if you change the value in the source object Mike, the value in the copy rose changes along with it.
There are many ways to implement a deep copy of an employee, and the simplest way is to manually assign the field one by one. However, this method is prone to error, that is, if the type of the field changes or increase or decrease, then the copy method will also have a corresponding change, so it is recommended to use the form of serialization for deep copy.
Since interface ICloneable has only one ambiguous clone method, it is only possible for us to implement two additional methods, declared as Deepclone and shallow, to implement both deep and shallow copies in a class. The final version of the employee should look like the following form:
[Serializable]classemployee:icloneable{ Public stringIdcode {Get;Set; } Public intAge {Get;Set; } PublicDepartment Department {Get;Set; } Public ObjectClone () {return This. MemberwiseClone (); } PublicEmployee Deepclone () {using(Stream Objectstream =NewMemoryStream ()) {IFormatter Formatter=NewBinaryFormatter (); Formatter. Serialize (Objectstream, This); Objectstream.seek (0, Seekorigin.begin); returnFormatter. Deserialize (Objectstream) asEmployee; } } PublicEmployee Shallowclone () {returnClone () asEmployee; }}
It is important to note the inclusion of serializable tags in the Department class;
The above is quoted from the 157 recommendations to improve C # programs with high-quality code
The correct realization of shallow copy and deep copy