【C#基础】浅拷贝&深拷贝

本文详细解释了C#中的浅拷贝与深拷贝概念,包括它们的区别、实现方式及示例代码。通过阅读本文,读者将了解如何在C#中正确地使用这两种拷贝方法。

C#中的浅拷贝和深拷贝

[所谓拷贝,即通过某种方式获得已知C#对象的一个副本]

问题一:什么是浅拷贝?


       浅 -> 如果该对象中包含值类型和引用类型,那么拷贝后得到的新的对象值类型为原有对象中值类型的一个副本,该值存储在新的地址空间内;而新对象中的引用类型存储的地址仍指向原对象中引用类型所指向的对象的内存空间(即两个引用都指向同一块内存空间)


问题二:什么是深拷贝?


       深  ->  与"浅"的不同之处在于拷贝得到的新对象中的引用类型所指向的对象虽然与原对象中引用类型所指向的对象具有相同的值,但是他们的内存空间是不同的(即新对象重新开辟了内存空间的来存储原对象中包含的引用类型对象)


问题三:如何实现浅拷贝?


       浅拷贝的实现很简单,.NET Framework为我们提供了一个ICloneable接口,只要实现接口的Clone方法,并调用当前对象的MemberwiseClone()方法即可实现,当然你也可以在Clone对象中创建一个新的对象,并把this中的值一个个赋值给新的对象,此处引用类型也直接赋值即可。代码如下:

 //实现ICloneable接口
    class Person:ICloneable
    {
        public string Name{get;set;}
        public int Age{get;set;}
        //每个人都有一只猫
        public Cat C{get;set;}

        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }

    class Cat
    {
        public string Name{get;set;}

        public override string ToString()
        {
            return "My cat's name is" + this.Name;
        }
    }
测试代码:
static void Main(string[] args)
        {
            Person p = new Person() { Name = "Dream", Age = 18, C = new Cat() { Name="Catty"} };

            Person pClone = p.Clone() as Person;
            Console.WriteLine(pClone.C);
            //浅拷贝:如果p.C发生改变,pClone.C也会发生同样的改变
            p.C.Name = "Snoppy";
            Console.WriteLine("改变p.C.Name后,pClone.C.Name的值:");
            Console.WriteLine(pClone.C);

            Console.ReadLine();
        }

问题四:如何实现深拷贝?


比较笨一点的方法就是如果拷贝的对象中仍包含引用对象,那么调用该引用对象的MemberwiseClone()即可,而值对象只需要简单的赋值即可,但是如果一个对象中包含了太多的引用对象,岂不是要对每一个对象都调用MemberwiseClone()方法么?所以:

       建议使用对象的序列化进行深拷贝!!!代码如下(只需要改动浅拷贝中的Clone方法即可,测试代码与浅拷贝中的测试代码一致):

public object Clone()
        {
            //使用内存流来传递数据
            using (Stream stream = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, this);
                stream.Seek(0, SeekOrigin.Begin);
                return formatter.Deserialize(stream) as Person;
            }
        }
注意:如果一个对象需要被序列化,必须在类上面写明可被序列化的标记代码

       建议:由于可以通过改写Clone方法来实现两种拷贝方式,为了区分拷贝的方式,只让Clone方法去实现一个浅拷贝,可以自己在类中定义深拷贝和浅拷贝的方法,并实现他们,在有需要的情况下。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值