C#浅拷贝和深拷贝实例解析

下面我将详细介绍一下 "C#浅拷贝和深拷贝实例解析" 的完整攻略。

一、浅拷贝和深拷贝的概念

在 C# 中,对象的拷贝方式有两种:浅拷贝和深拷贝。浅拷贝只是复制对象的引用,而不复制引用对象本身;深拷贝则是复制所有的引用对象。

二、浅拷贝和深拷贝的实现

1. 实现浅拷贝

在 C# 中,想要实现对象的浅拷贝,我们可以在该对象中添加一个 Clone() 方法。在 Clone() 方法中,我们只需要创建一个新的对象,并将原对象中所有的值类型成员复制给新对象,但对于引用类型的成员,我们只需要复制它们的引用即可。

接下来是一个浅拷贝示例:

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

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

class Address
{
    public string City { get; set; }
    public string Street { get; set; }
}

// 测试用例
Person person1 = new Person
{
    Name = "张三",
    Age = 18,
    Address = new Address { City = "北京", Street = "海淀区" }
};

Person person2 = person1.Clone();
person2.Address.City = "上海";

Console.WriteLine(person1.Address.City);  // 输出:上海

从上面的代码中可以看出,我们在 Person 类中添加了一个 Clone() 方法,而在这个方法中,我们调用了 Object 类的 MemberwiseClone() 方法,它能够创建一个当前对象的浅表副本。在该示例中,person1 和 person2 对象都拥有自己的地址引用,但这些引用指向的是同一个 Address 对象。所以当我们更新 person2.Address.City,实际上也会更新 person1.Address.City。

2. 实现深拷贝

那么如果我们想要实现深拷贝呢?在 C# 中,实现深拷贝的方式基本上有两种:手动拷贝和序列化。

手动实现深拷贝的方式是比较基础的。我们需要在创建新的对象时,对于引用类型的成员,我们需要递归每一个成员,依次创建新的对象并赋值。下面是一个手动实现深拷贝的示例:

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

    public Person Clone()
    {
        Address address = new Address { City = this.Address.City, Street = this.Address.Street };
        return new Person { Name = this.Name, Age = this.Age, Address = address };
    }
}

class Address
{
    public string City { get; set; }
    public string Street { get; set; }
}

// 测试用例
Person person1 = new Person
{
    Name = "张三",
    Age = 18,
    Address = new Address { City = "北京", Street = "海淀区" }
};

Person person2 = person1.Clone();
person2.Address.City = "上海";

Console.WriteLine(person1.Address.City);  // 输出:北京

从上面的代码中可以看出,我们在 Person 类中手动实现了 Clone() 方法。在这个方法中,我们递归的复制了每一个成员,生成了一个全新的对象。

当然,手动实现深拷贝是比较麻烦的,我们也可以使用 .NET 中的序列化和反序列化来实现深拷贝。我们只需要将携带了数据的对象序列化成二进制格式,再反序列化出新的对象即可实现深拷贝。下面是一个使用序列化实现深拷贝的示例:

using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

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

    public Person Clone()
    {
        BinaryFormatter formatter = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        formatter.Serialize(stream, this);
        stream.Position = 0;
        return (Person)formatter.Deserialize(stream);
    }
}

class Address
{
    public string City { get; set; }
    public string Street { get; set; }
}

// 测试用例
Person person1 = new Person
{
    Name = "张三",
    Age = 18,
    Address = new Address { City = "北京", Street = "海淀区" }
};

Person person2 = person1.Clone();
person2.Address.City = "上海";

Console.WriteLine(person1.Address.City);  // 输出:北京

从上面的代码中可以看出,我们在 Person 类中使用了 .NET 中的序列化和反序列化方法,先将 person1 对象序列化到一个内存流中,然后再从内存流中反序列化出 person2 对象。由于序列化和反序列化的过程都将创建新的对象,所以 person1 和 person2 对象拥有自己的地址引用,互不干扰。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#浅拷贝和深拷贝实例解析 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • C#分布式事务的超时处理实例分析

    C#分布式事务的超时处理实例分析 简介 本文将介绍在C#中处理分布式事务超时的实例,重点是针对传统的数据库操作,如何处理分布式事务超时的问题。 超时处理 在分布式事务中,一个事务可能会跨越多个数据库。当一个分布式事务出现了超时异常,我们需要对其进行处理。 超时处理有两个主要的目的: 避免事务无限制地等待,耗尽所有的资源 报告错误并撤销操作 下面介绍两个示例,…

    C# 2023年5月15日
    00
  • asp.net显示自己的网页图标的几种方式

    下面是“ASP.NET显示自己的网页图标的几种方式”的详细讲解,包括两个示例说明。 方式一:在HTML中引入favicon 在HTML页面的<head>标签中添加如下代码: <link rel="shortcut icon" href="/favicon.ico" type="image/x…

    C# 2023年6月3日
    00
  • 详解C# winform ListView的基本操作

    详解C# WinForm ListView的基本操作攻略 介绍 C# WinForm中的ListView是一种非常常用的用于显示数据的控件,本攻略将详细讲解如何使用C# WinForm ListView实现基本操作,包括: ListView的基本属性设置 列表视图、图标视图、详情视图和小图标视图的展示方式 添加、删除和编辑ListView的项 ListVie…

    C# 2023年6月1日
    00
  • C#实现的简单验证码识别实例

    下面是针对C#实现简单验证码识别的完整攻略: 1. 获取验证码图片 首先,需要下载验证码图片并将其保存到本地。可以使用下面的代码来实现: var webClient = new WebClient(); webClient.DownloadFile("http://example.com/captcha.png", "captc…

    C# 2023年6月7日
    00
  • C#从控制台读取字符串的方法

    接下来我将详细讲解“C#从控制台读取字符串的方法”。 什么是控制台? 控制台是计算机的一个系统软件,是一种在电脑上进行字符用户界面操作的应用程序,小巧、直观、灵活,是程序员和IT技术人员日常使用的一个工具。在Windows系统上,通过Win+R打开运行窗口,然后输入“cmd”就能打开控制台。 C#中如何从控制台读取字符串? 在C#中,我们可以使用Consol…

    C# 2023年6月8日
    00
  • 一篇文章彻底搞清楚c#中的委托与事件

    一篇文章彻底搞清楚C#中的委托与事件 委托 委托(Delegate)是一种类型,它可以持有函数的引用并执行这个函数。通过委托,我们可以在不知道函数名的情况下,直接访问和执行函数。 定义 在C#中,委托是定义在类的外部,但是要在类的内部定义具体的委托实例。委托的定义格式如下: public delegate void DelegateName(paramete…

    C# 2023年6月7日
    00
  • C#实现绘制随机噪点和直线

    请看下面: C#实现绘制随机噪点和直线 第一步:创建窗体和画布 首先,在Visual Studio的菜单栏中选择:File -> New -> Project,在弹出的窗口中选择:Windows Forms App(.NET Framework),取一个有意义的名称,然后点击创建按钮。 接下来,在弹出的窗口中选择:Form,创建一个窗体。然后在窗…

    C# 2023年6月6日
    00
  • asp.net(c#)中取得文件物理路径

    下面是详细的讲解“ASP.NET(C#)中取得文件物理路径”的完整攻略。 一、概述 在使用ASP.NET(C#)开发Web应用程序时,有时候需要获取Web应用程序中文件的物理路径,以便进行文件的读写操作。本攻略将介绍如何在ASP.NET(C#)中获取文件的物理路径。 二、获取文件的物理路径方法 下面介绍两种获取文件物理路径的方法: 1. 使用Server.M…

    C# 2023年6月1日
    00
合作推广
合作推广
分享本页
返回顶部