首页 > 编程语言 >C# 浅拷贝和深拷贝

C# 浅拷贝和深拷贝

时间:2023-09-15 18:56:27浏览次数:25  
标签:obj person C# 对象 Address 拷贝 public

浅拷贝:只复制对象的基本类型、对象类型、仍然属于原引用,也称为影子克隆

深拷贝:不止复制对象的基本类,同时也复制原对象中的对象,完全就是新对象产生的,也称为深度克隆

浅拷贝示例

类型基类System.Object已经为所有类型都实现了浅拷贝,类型所要做的就是公开一个复制的接口,而通常的,这个接口会借由实现ICloneable接口来实现。ICLoneable只包含一个Clone方法。该方法既可以被实现为浅拷贝也可以被实现为深拷贝,具体如何取舍需要根据具体类型的需求来决定。下面的代码提供了一个深拷贝的简单示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CloneTest
{
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public Address Address { get; set; }

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

    public class Address
    {
        public string Province { get; set; }

        public string City { get; set; }
    }
}
namespace CloneTest
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Person person = new Person();
            person.Name = "Test";
            person.Age = 30;
            person.Address = new Address() { Province = "GD", City = "PN" };

            Person shadow = person.Clone();
            shadow.Name = "Test1";
            shadow.Address.Province = "GX";

            Console.WriteLine($"person.Name: {person.Name}");
            Console.WriteLine($"shadow.Name: {shadow.Name}");
            Console.WriteLine($"person.Province: {person.Address.Province}");
            Console.WriteLine($"shadow.Province: {shadow.Address.Province}");
        }
    }
}

以上代码的执行结果如下

我们可以看的引用类型的属性Address一修改,两个类实例都跟着变化了

深拷贝示例

深拷贝是指复制对象的所有数据,包括对象内部引用的其他对象。这意味着,新的对象和原始对象不共享任何数据,它们是完全独立的。可以通过以下方式实现

1.反射的方式实现

public static T DeepCopy<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, DeepCopyByFS(field.GetValue(obj)));
                }
                catch
                {
                }
            }
            return (T)retval;
        }

2.二进制序列化方式实现

public static T DeepCopy<T>(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;
        }

使用该方式进行序列化,需要在对应的类上添加[Serializable]特性的

3.使用Newtonsoft.Json进行序列化和反序列化

public static T DeepCopyByNJ<T>(T obj)
        {
            if (obj == null)
            {
                return default(T);
            }
            T object2 = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(Newtonsoft.Json.JsonConvert.SerializeObject(obj));

            return object2;
        }

需要Nuget安装包Newtonsoft.Json

以上的运行结果均为

区别

浅拷贝:是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用类型的字段则指复制它的一个引用到目标对象。如果改变目标对象中引用型字段的值它将反应在原始对象中,也就是说原始对象中对应的字段也会发生变化。

深拷贝:与浅拷贝的不同是对于引用的处理,深拷贝将会在内存中创建一个新的对象,对应字段和原始对象完全相同。也就是说这个引用和原始对象的引用是不相同的,因为新对象与原对象引用地址不同,我们在改变新对象中的这个字段的时候是不会影响到原始字段中对应字段的内容。

标签:obj,person,C#,对象,Address,拷贝,public
From: https://www.cnblogs.com/SmallCarp/p/17705734.html

相关文章

  • 零拷贝技术:减少数据复制和上下文切换,提高网络传输效率(下)
    前章回顾在前一章节中,我们了解了DMA技术在文件传输中的重要性,并简要介绍了零拷贝技术。为了提高文件传输的性能,我们需要减少用户态与内核态之间的上下文切换次数以及内存拷贝次数。本章将深入探讨零拷贝技术的优化方法,让我们一起走进零拷贝的优化之路!如何优化文件传输的性能?当......
  • Codeforces Round 773 (Div. 2) B. Power Walking
    有\(n\)个增幅道具,第\(i\)个道具种类为\(a_i\),一个人的强度\(w\)为他所有道具的种类数。对于\(k]\in[1,n]\),询问将\(n\)个道具分配给\(k\)个人且每个人至少分配到一个道具后,能够得到的最想强度和\(\sum_{i=1}^{n}w_i\)。观察一:最低强度和\(\sum_{i=1}^{k}w......
  • Docker 安装与配置
    安装方法:yum配置仓库安装rpm包安装使用docker官方提供的自动化脚本这里以yum配置仓库安装为例。确认操作系统版本确认操作系统是否是CentOS7及以上版本。cat/etc/os-release卸载旧版本sudoyumremovedocker\docker-client\......
  • Scrum敏捷开发管理流程,从产品路线图-需求-迭代-缺陷等
    ​Leangoo领歌是Scrum中文网(scrum.cn)旗下的一款永久免费的敏捷研发管理工具。Leangoo领歌覆盖了敏捷研发全流程,它提供端到端敏捷研发管理解决方案,包括小型团队敏捷开发,规模化敏捷SAFe,ScrumofScrums大规模敏捷,涵盖敏捷需求管理、任务协同、进展跟踪、缺陷管理、统计度量等。提......
  • xctf ics-05
     进来之后是一个工控云管理系统,左边一堆只有设备维护中心有跳转。  此时的url也发生了改变 没头绪,到处瞎点试一试 发现点了左上角的设备维护中心之后有变化,并且参数会显示出来。  修改参数发现始终会显示在页面下方 使用index.php,返回ok 尝试读取index.......
  • library cache lock故障分析
    现象客户数据库在每周五出现大量的“librarycachelock”等待事件,数据库业务办理失败。问题分析从ASH视图我们可以发现,数据库从9:01分开始出现“librarycachelock”等待事件。如上图,等待事件中P3TEXT对应的是100*mode+namespace,对于的P3RAW十六进制值为52002。namespace52转为......
  • Launcher3 中 IconCache 缓存逻辑
    概述我们先看下IconCache的初始化过程,接着看下IconCache核心数据结构、算法,最后介绍与之关联的几个类。Launcher.javapublicclassLauncherextendsStatefulActivity<LauncherState>implements...{...publicstaticfinalStringTAG="Launcher";privateLau......
  • 华为认证 | 考HCIE,真的不需要先考HCIP
    HCIA是初级,HCIP是中级,HCIE是高级认证,大家都懂。但总有人问,考HCIE要先考HCIA和HCIP吗?今天跟你说说这个!01考HCIE需要先考HCIP么?考HCIE认证没有什么限制,专业、经验等级都没有限制,只要想考HCIE,就可以直接报考HCIE认证,不用先考HCIA或HCIP认证的。虽然不需要先拿到HCIA、HCIP才能报考HCI......
  • Socks5代理与网络安全:保护隐私、绕过限制与爬虫应用
    1.Socks5代理简介Socks5代理是一种网络协议,允许数据在客户端与服务器之间进行传输。与HTTP代理不同,Socks5代理不仅支持TCP连接,还可以处理UDP流量,因此在某些需要实时数据传输的场景中表现出色。它能够代理各种应用层协议,为用户提供更灵活的网络体验。2.保护隐私与匿名性一个重要的......
  • 无涯教程-JavaScript - INDIRECT函数
    描述INDIRECT函数返回由文本字符串指定的引用。如果您在Excel公式中键入引用B1,则Excel会理解这引用了单元格B1。但是,Excel无法将文本字符串"B1"理解为引用。因此,如果单元格引用采用文本字符串的形式,则需要使用INDIRECT函数将其转换为实际的单元格引用。立即判断引用以显......