zoukankan      html  css  js  c++  java
  • 浅拷贝与深拷贝

    前言

    本文以C#为例,说明什么是浅拷贝,什么是深拷贝,以及如何应用序列化快速深拷贝。

    目录

    • 浅拷贝与深拷贝简单说明
    • 浅拷贝
    • 复杂对象的浅拷贝
    • 深拷贝
    • 通过序列化深拷贝
    • 参考

    浅拷贝与深拷贝简单说明

    无论是浅拷贝与深拷贝,C#都将源对象中的所有字段复制到新的对象中。不过,对于值类型字段,引用类型字段以及字符串类型字段的处理,两种拷贝方式存在一定的区别。

    拷贝类型 字段 拷贝操作详情 副本或源对象中修改是否相互影响
    浅拷贝 值类型 字段被拷贝到副本中 不会
    浅拷贝 引用类型 字段被拷贝到副本中
    深拷贝 值类型 字段被重新创建并赋值 不会
    深拷贝 引用类型 字段被重新创建并赋值 不会

    浅拷贝

    浅拷贝可以利用MemberwiseClone方法实现,具体代码如下:

    using System;
    
    namespace CopyTest
    {
        public class Person : ICloneable
        {
            public string Name { get; set; }
            public int Age { get; set; }
    
            public Object Clone()
            {
                return this.MemberwiseClone() ;
            }
        }
    }
    
    
    using System;
    
    namespace CopyTest
    {
        public class PersonTest
        {
            public static void Test()
            {
                Test1();
                Test2();
            }
    
            public static void Test1()
            {
                Person p1 = new Person();
                p1.Name = "zhao";
                p1.Age = 20;
    
                Person p2 = p1;
                p2.Name = "li";
                Console.WriteLine(p1.Name);
            }
    
            public static void Test2()
            {
                Person p1 = new Person();
                p1.Name = "zhao";
                p1.Age = 20;
    
                Person p2 = p1.Clone() as Person;
                p2.Name = "li";
                Console.WriteLine(p1.Name);
            }
    
        }
    }
    
    

    输出:

    li
    zhao
    

    可见,通过浅拷贝,修改对象的值类型属性或字符串不影响拷贝对象;不浅拷贝只=是不行的。

    复杂对象的浅拷贝

    所谓复杂对象,指的是对象里面包含了对象(引用类型),而不是简单的值类型和字符串。比如:

    using System;
    
    namespace CopyTest
    {
        public class Car:ICloneable
        {
            public string Name { get; set; }
            public Person Driver { get; set; }
    
            public object Clone()
            {
                return this.MemberwiseClone();
            }
        }
    }
    
    

    这种情况下的浅拷贝是不会拷贝引用类型的。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CopyTest
    {
        class CarTest
        {
            public static void Test()
            {
                Car c1 = new Car();
                c1.Name = "audi";
                Person p1 = new Person();
                p1.Name = "wang";
                p1.Age = 20;
                c1.Driver = p1; 
                Car c2 = c1.Clone() as Car;
                c2.Name = "bmw";
                c2.Driver.Name = "li";
                Console.WriteLine(c1.Driver.Name);
            }
        }
    }
    
    

    输出

    audi	li
    

    修改driver对c1有影响。解决这种问题,需要用深拷贝。

    深拷贝

    深拷贝需要单独写方法,代码如下:

    using System;
    
    namespace CopyTest
    {
        public class NewCar : ICloneable
        {
            public string Name { get; set; }
            public Person Driver { get; set; }
    
            public object Clone()
            {
                NewCar ret = new NewCar();
                ret.Name = this.Name;
                ret.Driver = new Person();
                ret.Driver.Name = this.Driver.Name;
                ret.Driver.Age = this.Driver.Age;
                return ret;
            }
        }
    }
    
    

    测试代码

    using System;
    
    namespace CopyTest
    {
        public class NewCarTest
        {
            public static void Test()
            {
                NewCar c1 = new NewCar();
                c1.Name = "audi";
                Person p1 = new Person();
                p1.Name = "wang";
                p1.Age = 20;
                c1.Driver = p1;
                NewCar c2 = c1.Clone() as NewCar;
                c2.Name = "bmw";
                c2.Driver.Name = "li";
                Console.WriteLine(c1.Driver.Name);
            }
        }
    }
    
    

    输出:

    audi	wang
    

    通过序列化深拷贝

    序列号的基本原理在这里不介绍了,我们可以应用序列号快速进行深拷贝,修改后的代码如下:

    using System;
    using System.IO;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace CopyTest
    {
        [Serializable]
        public class NewCar : ICloneable
        {
            public string Name { get; set; }
            public Person Driver { get; set; }
    
            public object Clone()
            {
                using (Stream objectStream = new MemoryStream())
                {
                    IFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(objectStream, this);
                    objectStream.Seek(0, SeekOrigin.Begin);
                    return formatter.Deserialize(objectStream);
                }
            }
        }
    }
    
    

    参考

    例说C#深拷贝与浅拷贝

  • 相关阅读:
    生活娱乐 工业机器人代替工人装配鼠标键盘
    生活娱乐 工商银行如何查询开户行
    生活娱乐 格力空气能热水器怎么样
    生活娱乐 岛城将开首家机器人餐厅
    生活娱乐 毕业生论文查重技巧
    Windows 老是弹出要自动拨号连接怎么办
    Office 针式打印机如何调节边距
    Office 如何打印彩色照片能取得较好的效果
    西游释厄传如何设置简化出招表
    [ES2019] Use JavaScript ES2019 flatMap to Map and Filter an Array
  • 原文地址:https://www.cnblogs.com/wardensky/p/4230912.html
Copyright © 2011-2022 走看看