C#中的浅拷贝(Shallow Copy)和深拷贝(Deep Copy),深拷贝的集中实现方式,浅拷贝深拷贝的案例

C#中的浅拷贝(Shallow Copy)和深拷贝(Deep Copy)

拷贝就是创建一个对象,这个对象有着原始对象数据(属性和字段)的一份精确拷贝(只针对ObjectArray这样的引用数据类型)。
换个说法就是:所谓的对象拷贝(复制)就是为对象创建副本,得到相同的对象。

浅拷贝(又称为影子拷贝):(1)如果对象属性的值是值类型和string类型,拷贝的就是基本类型的值;
(2)如果对象属性是引用类型,拷贝的就是引用类型(string除外)的引用(也就是堆地址);所以修改其中一个对象引用类型数据,会影响到另一个对象;
(3)浅拷贝使用的是Object.MemberwiseClone()方法。

浅拷贝出来的副本对象中,对象里的数据(属性和字段)如果是值类型和string类型,栈中保存的就是数据自身,在原始对象和副本对象中修改值类型数据,不会相互影响(因为值类型自身在栈中有不同的内存空间);如果是引用类型,浅拷贝只是拷贝引用类型的引用(也就是堆地址),所以在原始对象和副本对象中修改引用类型数据,会相互影响(因为原始对象和副本对象拥有同一个堆地址的引用)。
在这里插入图片描述
深拷贝:(1)完全将对象中的所有数据(属性和字段)都复制到副本对象中;
(2)引用类型的数据(属性和字段)会被重新创建并且复制;所以修改其中一个对象引用类型数据,不会影响到另一个对象。

深拷贝出来的副本对象中,对象里的数据(属性和字段)如果是值类型和string类型,栈中保存的就是数据自身在原始对象和副本对象中修改值类型数据,不会相互影响(因为值类型自身在栈中有不同的内存空间);如果是引用类型,深拷贝会重新创建引用类型的数据(属性和字段)并且复制原始对象中引用类型的数据的值(堆地址中保存的具体的值),所以在原始对象和副本对象中修改引用类型数据,不会相互影响。
在这里插入图片描述

浅拷贝和深拷贝在复制原型设计模式中的对象中起着重要作用。

C#中实现深拷贝的几种方式:
1.创建一个构造函数,在构造函数中将原始对象的值一一赋值给新对象。(当对象中的变量较少的话,可以使用)

2.首先浅拷贝对象,然后重新创建对象中的引用类型的变量。

3.通过对象的序列化和反序列化功能
(1)二进制序列化和反序列化
(2)xml序列化和反序列化
(3)Json序列化和反序列化

4.通过反射和递归实现

浅拷贝和深拷贝的示例代码:

namespace ShallowAndDeepCopy
{
    internal class Program
    {
        //年级
        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 Student DeepCopy(int stu_Grade)
            {
                Student student = (Student)this.MemberwiseClone();
                student.Grade = new Grade() { Stu_Grade = stu_Grade };
                return student;
            }
        }

        private static void Main(string[] args)
        {
            Console.WriteLine("-----------------下面是浅拷贝深拷贝的测试代码----------------");

            //创建一个原始学生对象stu1并初始化所有字段
            Student stu1 = new Student();
            stu1.Name = "张三";
            stu1.Age = 18;
            stu1.Grade = new Grade() { Stu_Grade = 8 };

            //声明一个学生对象,保存stu1浅拷贝的副本对象的信息
            Student stu2 = stu1.ShallowCopy();
            Console.WriteLine("浅拷贝后stu1和stu2学生信息输出:");
            Console.WriteLine("学生stu1的信息:");
            //输出学生信息
            OutStuMsg(stu1);
            Console.WriteLine("学生stu2的信息:");
            //输出学生信息
            OutStuMsg(stu2);

            //修改浅拷贝副本对象的信息
            stu2.Name = "李四";
            stu2.Age = 20;
            stu2.Grade.Stu_Grade = 9;
            Console.WriteLine("浅拷贝后修改stu2学生后stu1和stu2信息输出:");
            Console.WriteLine("学生stu1的信息:");
            //输出学生信息
            OutStuMsg(stu1);
            Console.WriteLine("学生stu2的信息:");
            //输出学生信息
            OutStuMsg(stu2);

            //声明一个学生对象,保存stu1浅拷贝的副本对象的信息
            Student stu3 = stu1.DeepCopy(7);
            Console.WriteLine("深拷贝后stu1和stu3信息输出:");
            Console.WriteLine("学生stu1的信息:");
            //输出学生信息
            OutStuMsg(stu1);
            Console.WriteLine("学生stu3的信息:");
            //输出学生信息
            OutStuMsg(stu3);

            //修改深拷贝副本对象的信息
            stu3.Name = "王麻子";
            stu3.Age = 25;
            stu3.Grade.Stu_Grade = 10;
            Console.WriteLine("深拷贝后修改stu3学生后stu1和stu3信息输出:");
            Console.WriteLine("学生stu1的信息:");
            //输出学生信息
            OutStuMsg(stu1);
            Console.WriteLine("学生stu3的信息:");
            //输出学生信息
            OutStuMsg(stu3);
        }

        public static void OutStuMsg(Student student)
        {
            Console.WriteLine($"姓名:{student.Name}    年龄:{student.Age}");
            Console.WriteLine($"年级:{student.Grade.Stu_Grade} \n");
        }
    }
}

运行结果:
在这里插入图片描述
参考文章:
http://t.csdnimg.cn/qLenZ
https://docs.microsoft.com/zh-tw/dotnet/api/system.object.memberwiseclone?view=net-6.0

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python,拷贝指的是创建一个新的对象,包含原始对象的所有内容。但是,深拷贝浅拷贝会根据拷贝方式的不同,影响拷贝结果。 深拷贝Deep Copy)是指创建一个新的对象,包含原始对象的所有内容,甚至包括原始对象引用的对象。也就是说,深拷贝会递归地复制所有对象,包括它们的内部对象。深拷贝的结果是两个完全独立的对象,修改一个对象不会影响另一个对象。 浅拷贝Shallow Copy)是指创建一个新的对象,包含原始对象的所有内容,但不会递归复制原始对象引用的对象。也就是说,浅拷贝只复制对象的顶层内容,而不会对其内部对象进行复制。浅拷贝的结果是两个对象共享同一个内部对象,修改一个对象会影响另一个对象。 下面是一个例子,可以更好地说明深拷贝浅拷贝的区别: ```python import copy # 定义一个列表 a = [1, 2, [3, 4]] # 浅拷贝 b = copy.copy(a) # 深拷贝 c = copy.deepcopy(a) # 修改a的第二个元素 a[1] = 5 # 修改a的第三个元素的第一个元素 a[2][0] = 6 # 输出a、b、c的值 print(a) # [1, 5, [6, 4]] print(b) # [1, 2, [6, 4]] print(c) # [1, 2, [3, 4]] ``` 在上面的例子,我们先定义了一个列表a,它包含了一个嵌套列表。我们使用copy.copy()和copy.deepcopy()对a进行拷贝,并修改原始列表a的值。最后,我们输出了三个列表的值,可以看到,浅拷贝b的第三个元素的值也被修改了,而深拷贝c的值没有受到影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值