说明
浅拷贝
指的是拷贝一个对象时,仅仅拷贝对象的引用,即两个对象还是引用同一份实体。此时,其中一个对象的改变会影响到另一个对象。
深拷贝
指的是拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一起拷贝。这样拷贝后的对象就和源对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。
实现方式
浅拷贝
对象继承接口ICloneable,重写Clone方法。
伪代码如下:
public class classA : ICloneable{public object Clone(){return this.MemberwiseClone();}}
上面代码中使用.NET提供的MemberwiseClone()方法来实现浅拷贝。
深拷贝
实现深拷贝,有以下方式:
1,上述Clone()方法体中,不用浅拷贝的MemberwiseClone()方法,通过重新开辟对象内存,以及重新开辟对象引用对象成员内存的方式,来实现深拷贝。
2,序列化,反序列化的方式
// 利用XML序列化和反序列化实现public static T DeepCopyWithXmlSerializer(T obj){object retval;using (MemoryStream ms = new MemoryStream()){XmlSerializer xml = new XmlSerializer(typeof(T));xml.Serialize(ms, obj);ms.Seek(0, SeekOrigin.Begin);retval = xml.Deserialize(ms);ms.Close();}return (T)retval;}// 利用二进制序列化和反序列实现public static T DeepCopyWithBinarySerialize(T obj){object retval;using (MemoryStream ms = new MemoryStream()){BinaryFormatter bf = new BinaryFormatter();// 序列化成流bf.Serialize(ms, obj);ms.Seek(0, SeekOrigin.Begin);// 反序列化成对象retval = bf.Deserialize(ms);ms.Close();}return (T)retval;}
3,反射的方式
下述两种反射方式,要求:实体类有个无参的构造方法。且都没有解决类和类之间循环引用的问题
/// /// 对象拷贝/// /// 被复制对象/// 新对象private object CopyOjbect(object obj) {if (obj == null) {return null;}Object targetDeepCopyObj;Type targetType = obj.GetType();//值类型 if (targetType.IsValueType == true|| targetType.FullName == "System.String") {targetDeepCopyObj = obj;}//引用类型 else {targetDeepCopyObj = System.Activator.CreateInstance(targetType); //创建引用对象 System.Reflection.MemberInfo[] memberCollection = obj.GetType().GetMembers();foreach (System.Reflection.MemberInfo member in memberCollection) {//拷贝字段if (member.MemberType == System.Reflection.MemberTypes.Field){System.Reflection.FieldInfo field = (System.Reflection.FieldInfo)member;Object fieldValue = field.GetValue(obj);if (fieldValue is ICloneable){field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone());}else{field.SetValue(targetDeepCopyObj, CopyOjbect(fieldValue));}}//拷贝属性else if (member.MemberType == System.Reflection.MemberTypes.Property) {System.Reflection.PropertyInfo myProperty = (System.Reflection.PropertyInfo)member;MethodInfo info = myProperty.GetSetMethod(false);if (info != null) {try {object propertyValue = myProperty.GetValue(obj, null);if (propertyValue is ICloneable) {myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null);}else {myProperty.SetValue(targetDeepCopyObj, CopyOjbect(propertyValue), null);}}catch (System.Exception ex) {}}}}}return targetDeepCopyObj;}
// 利用反射实现深拷贝public static T DeepCopyWithReflection(T obj){Type type = obj.GetType();// 如果是字符串或值类型则直接返回if (obj is string || type.IsValueType) return obj;if (type.IsArray){Type elementType = Type.GetType(type.FullName.Replace("[]", string.Empty));var array = obj as Array;Array copied = Array.CreateInstance(elementType, array.Length);for (int i = 0; i
补充
下面代码,通过引用赋值和new重新分配内存的方式,完成了s–>s1和s–>s2的深拷贝。
Student s = new Student(“张成”, 21);
Student s1 = s;
s = new Student(“郭立强”, 32);
Student s2 = s;
![在这里插入图片描述](https://img.php1.cn/3cd4a/1eebe/cd5/6c257b6ba227cc3e.webp)