文章目录
- 1.深拷贝
- 2.浅拷贝
- 3.拷贝类
- 4.浅拷贝的实现
- 5.深拷贝实现
- 5.1 浅拷贝对象,对引用类型重新一个个赋值
- 5.2 反射实现
- 5.3 利用XML序列化和反序列化实现
1.深拷贝
拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一起拷贝。这样进行深拷贝后的拷贝对象就和源对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。
int source = 123;
// 值类型赋值内部执行深拷贝
int copy = source;
// 对拷贝对象进行赋值不会改变源对象的值
copy = 234;
Console.WriteLine($"source = {source},copy = {copy}"); // 123 234
// 同样对源对象赋值也不会改变拷贝对象的值
source = 345;
Console.WriteLine($"source = {source},copy = {copy}"); // 345 234
深拷贝示意图:
2.浅拷贝
==拷贝一个对象时,仅仅拷贝对象的引用进行拷贝,但是拷贝对象和源对象还是引用同一份实体。==此时,其中一个对象的改变都会影响到另一个对象。
public class Person
{public string Name { get; set; }
}public static void Main(string[] args)
{Person sourceP = new Person() { Name = "张三" };Person copyP = sourceP; // 浅拷贝copyP.Name = "张老三"; // 拷贝对象改变Name值,源对象Name值也会改变Console.WriteLine("Person.Name: [SourceP: {0}] [CopyP:{1}]", sourceP.Name, copyP.Name); // 张老三 张老三
}
浅拷贝示意图:
3.拷贝类
//年级
public class Grade
{public int Stu_Grade { get; set; }
}//学生
public class Student
{public string Name { get; set; }public int Age { get; set; }public Grade Grade { get; set; }// 调用Object的MemberwiseClone方法实现浅拷贝public Student ShallowCopy(){return (Student)this.MemberwiseClone();}// 输出学生信息public override string ToString(){return $"姓名:{Name},年龄:{Age},年纪:{Grade.Stu_Grade}";}
}
4.浅拷贝的实现
浅拷贝的实现是调用受保护的方法Object.MemberwiseClone()
public static void Main(string[] args)
{Student sourceStu = new Student{Name = "ming",Age = 18,Grade = new Grade{ Stu_Grade = 6 }};Student copyStu = sourceStu.ShallowCopy();// 输出修改信息前,源学生和拷贝学生信息Console.WriteLine("------修改前------");Console.WriteLine("源学生信息" + sourceStu.ToString());Console.WriteLine("拷贝信息" + copyStu.ToString());copyStu.Name = "Tom";copyStu.Age = 26;copyStu.Grade.Stu_Grade = 10;// 输出修改信息后,源学生和拷贝学生信息Console.WriteLine("------修改后------");Console.WriteLine("源学生信息" + sourceStu.ToString());Console.WriteLine("拷贝信息" + copyStu.ToString());
}
输出:
------修改前------
源学生信息姓名:ming,年龄:18,年级:6
拷贝信息姓名:ming,年龄:18,年级:6
------修改后------
源学生信息姓名:ming,年龄:18,年级:10
拷贝信息姓名:Tom,年龄:26,年级:10
5.深拷贝实现
5.1 浅拷贝对象,对引用类型重新一个个赋值
public Student DeepCopy()
{Student student = (Student)this.MemberwiseClone();student.Grade = new Grade{ Stu_Grade = student.Grade.Stu_Grade };return student;
}
采用和浅拷贝一样的测试数据进行测试,输出:
------修改前------
源学生信息姓名:ming,年龄:18,年级:6
拷贝信息姓名:ming,年龄:18,年级:6
------修改后------
源学生信息姓名:ming,年龄:18,年级:6
拷贝信息姓名:Tom,年龄:26,年级:10
5.2 反射实现
拷贝对象:
//年级
public class Grade
{public int Stu_Grade { get; set; }
}// 成绩
public class Score
{public Science Science { get; set; }public Arts Arts { get; set; }
}// 理科
public class Science
{// 数学public int Math { get; set; }
}// 文科
public class Arts
{// 语文public int Chinese { get; set; }
}//学生
public class Student
{public string Name { get; set; }public int Age { get; set; }public Grade Grade { get; set; }public Score Scroe { get; set; }
}
深拷贝实现:
public class DeepCopyHelper
{// 反射实现深拷贝public static T DeepCopyByReflect<T>(T obj){//如果是字符串或值类型则直接返回if (obj is string || obj.GetType().IsValueType) return obj;object retval = Activator.CreateInstance(obj.GetType());FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);foreach (FieldInfo field in fields){// 解决层次引用类型try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); }catch { }}return (T)retval;}
}
测试:
public static void Main(string[] args)
{Student sourceStu = new Student{Name = "ming",Age = 18,Grade = new Grade{ Stu_Grade = 6 },Scroe = new Score{ Arts = new Arts{Chinese = 90}, Science = new Science{Math = 90}}};Student copyStu = DeepCopyHelper.DeepCopyByReflect<Student>(sourceStu);// 输出修改信息前,源学生和拷贝学生信息Console.WriteLine("------修改前------");Console.WriteLine("源学生信息" + sourceStu.ToString());Console.WriteLine("拷贝信息" + copyStu.ToString());copyStu.Name = "Tom";copyStu.Age = 26;copyStu.Grade.Stu_Grade = 10;copyStu.Scroe.Arts.Chinese = 100;copyStu.Scroe.Science.Math = 100;// 输出修改信息后,源学生和拷贝学生信息Console.WriteLine("------修改后------");Console.WriteLine("源学生信息" + sourceStu.ToString());Console.WriteLine("拷贝信息" + copyStu.ToString());
}
结果:
------修改前------
源学生信息姓名:ming,年龄:18,年级:6, 成绩:(语文:90,数学:90)
拷贝信息姓名:ming,年龄:18,年级:6, 成绩:(语文:90,数学:90)
------修改后------
源学生信息姓名:ming,年龄:18,年级:6, 成绩:(语文:90,数学:90)
拷贝信息姓名:Tom,年龄:26,年级:10, 成绩:(语文:100,数学:100)
5.3 利用XML序列化和反序列化实现
测试内容和结果和5.2一样
// xml 实现深拷贝
public static T DeepCopyByXml<T>(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;
}