首页 后端开发 C#.Net教程 C#浅拷贝和深拷贝实例解析

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

Jan 19, 2017 am 11:41 AM

在有些时候,我们需要从数据库读取数据填充对象或从硬盘读取文件填充对象,但是这样做相对耗时。这时候我们就想到了对象的拷贝。本文即以实例形式解析了C#浅拷贝和深拷贝的用法。具体如下:

一、浅拷贝

1.什么是"浅拷贝":

当针对一个对象前拷贝的时候,对于对象的值类型成员,会复制其本身,对于对象的引用类型成员,仅仅复制对象引用,这个引用指向托管堆上的对象实例。

2.有一个对象,包含引用类型的类成员和值类型的struct成员

Cinema包含引用类型成员Room和值类型成员Film。

public class Room
{
  public int _maxSeat;
 
  public Room(int maxSeat)
  {
    this._maxSeat = maxSeat;
  }
}
 
public struct Film
{
  public string _name;
 
  public Film(string name)
  {
    this._name = name;
  }
}
 
public class Cinema
{
  public Room _room;
  public Film _film;
 
  public Cinema(Room room, Film film)
  {
    this._room = room;
    this._film = film;
  }
 
  public object Clone()
  {
    return MemberwiseClone(); //对引用类型实施浅复制
  }
}
登录后复制

3.测试拷贝后的效果

①打印出原先对象拷贝前值类型和引用类型成员的值
②对原先对象拷贝,打印出复制对象值类型和引用类型成员的值
③改变原先对象的值,再次打印原先对象的值类型和引用类型成员的值
④再次打印复制对象值类型和引用类型成员的值

static void Main(string[] args)
{
  Room room1 = new Room(60);
  Film film1 = new Film("家园防线");
  Cinema cinema1 = new Cinema(room1, film1);
  Cinema cinema2 = (Cinema)cinema1.Clone();
  Console.WriteLine("拷贝之前,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name,cinema1._room._maxSeat);
 
  Console.WriteLine("拷贝之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);
 
  //修改拷贝之前引用类型的字段值
  cinema1._film._name = "极品飞车";
  cinema1._room._maxSeat = 80;
 
  Console.WriteLine("修改之后,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name, cinema1._room._maxSeat);
  Console.WriteLine("修改之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);
 
  Console.ReadKey();
}
登录后复制

分析:

浅拷贝关键点是对引用类型拷贝的是对象引用,这个引用指向托管堆上的对象实例。改变原对应引用类型的值,会影响到复制对象。

二、深拷贝

1.什么是"深拷贝"

对引用成员指向的对象也进行复制,在托管堆上赋值原先对象实例所包含的数据,再在托管堆上创建新的对象实例。

2.通过对每个对象成员进行复制进行深拷贝

public object Clone()
{
  Room room = new Room();
  room._maxSeat = this._room._maxSeat;//复制当前引用类型成员的值到新对象
  Film film = this._film; //值类型直接赋值
  Cinema cinema = new Cinema(room, film);
  return cinema;
}
登录后复制

3.也可以通过序列化和反序列化进行深拷贝

public object Clone1()
{
  BinaryFormatter bf = new BinaryFormatter();
  MemoryStream ms = new MemoryStream();
  bf.Serialize(ms, this); //复制到流中
  ms.Position = 0;
  return (bf.Deserialize(ms));
}
登录后复制

4.采用序列化和反序列化深拷贝,但必须把所有的类打上[Serializable],测试代码如下:

[Serializable]
public class Room
{
  public int _maxSeat;
 
  public Room()
  {}
 
  public Room(int maxSeat)
  {
    this._maxSeat = maxSeat;
  }
}
 
[Serializable]
public struct Film
{
  public string _name;
 
  public Film(string name)
  {
    this._name = name;
  }
}
 
[Serializable]
public class Cinema
{
  public Room _room;
  public Film _film;
 
  public Cinema(Room room, Film film)
  {
    this._room = room;
    this._film = film;
  }
 
  //浅拷贝
  //public object Clone()
  //{
  //  return MemberwiseClone(); //对引用类型实施浅复制
  //}
 
  //深拷贝 对每个对象成员进行复制
  public object Clone()
  {
    Room room = new Room();
    room._maxSeat = this._room._maxSeat;//复制当前引用类型成员的值到新对象
    Film film = this._film; //值类型直接赋值
    Cinema cinema = new Cinema(room, film);
    return cinema;
  }
 
  //使用序列化和反序列化进行复制
  public object Clone1()
  {
    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream ms = new MemoryStream();
    bf.Serialize(ms, this); //复制到流中
    ms.Position = 0;
    return (bf.Deserialize(ms));
  }
}
登录后复制

5.测试拷贝后的效果

①打印出原先对象拷贝前值类型和引用类型成员的值
②对原先对象拷贝,打印出复制对象值类型和引用类型成员的值
③改变原先对象的值,再次打印原先对象的值类型和引用类型成员的值
④再次打印复制对象值类型和引用类型成员的值

static void Main(string[] args)
   {
     Room room1 = new Room(60);
     Film film1 = new Film("家园防线");
     Cinema cinema1 = new Cinema(room1, film1);
     Cinema cinema2 = (Cinema)cinema1.Clone1();
     Console.WriteLine("拷贝之前,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name,cinema1._room._maxSeat);
 
     Console.WriteLine("拷贝之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);
 
     //修改拷贝之前引用类型的字段值
     cinema1._film._name = "极品飞车";
     cinema1._room._maxSeat = 80;
 
     Console.WriteLine("修改之后,结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema1._film._name, cinema1._room._maxSeat);
     Console.WriteLine("修改之后,新的结构成员的字段值为{0},引用类型成员的字段值为{1}", cinema2._film._name, cinema2._room._maxSeat);
 
     Console.ReadKey();
   }
登录后复制

   

结果:

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

分析:

深拷贝后,两个对象的引用成员已经分离,改变原先对象引用类型成员的值并不会对复制对象的引用类型成员值造成影响。

更多C#浅拷贝和深拷贝实例解析相关文章请关注PHP中文网!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1667
14
CakePHP 教程
1426
52
Laravel 教程
1328
25
PHP教程
1273
29
C# 教程
1255
24
c#.net的持续相关性:查看当前用法 c#.net的持续相关性:查看当前用法 Apr 16, 2025 am 12:07 AM

C#.NET依然重要,因为它提供了强大的工具和库,支持多种应用开发。1)C#结合.NET框架,使开发高效便捷。2)C#的类型安全和垃圾回收机制增强了其优势。3).NET提供跨平台运行环境和丰富的API,提升了开发灵活性。

从网络到桌面:C#.NET的多功能性 从网络到桌面:C#.NET的多功能性 Apr 15, 2025 am 12:07 AM

C#.NETisversatileforbothwebanddesktopdevelopment.1)Forweb,useASP.NETfordynamicapplications.2)Fordesktop,employWindowsFormsorWPFforrichinterfaces.3)UseXamarinforcross-platformdevelopment,enablingcodesharingacrossWindows,macOS,Linux,andmobiledevices.

c#.net适合您吗?评估其适用性 c#.net适合您吗?评估其适用性 Apr 13, 2025 am 12:03 AM

c#.netissutableforenterprise-levelapplications withemofrosoftecosystemdueToItsStrongTyping,richlibraries,androbustperraries,androbustperformance.however,itmaynotbeidealfoross-platement forment forment forment forvepentment offependment dovelopment toveloperment toveloperment whenrawspeedsportor whenrawspeedseedpolitical politionalitable,

C#作为多功能.NET语言:应用程序和示例 C#作为多功能.NET语言:应用程序和示例 Apr 26, 2025 am 12:26 AM

C#在企业级应用、游戏开发、移动应用和Web开发中均有广泛应用。1)在企业级应用中,C#常用于ASP.NETCore开发WebAPI。2)在游戏开发中,C#与Unity引擎结合,实现角色控制等功能。3)C#支持多态性和异步编程,提高代码灵活性和应用性能。

C#.NET与未来:适应新技术 C#.NET与未来:适应新技术 Apr 14, 2025 am 12:06 AM

C#和.NET通过不断的更新和优化,适应了新兴技术的需求。1)C#9.0和.NET5引入了记录类型和性能优化。2).NETCore增强了云原生和容器化支持。3)ASP.NETCore与现代Web技术集成。4)ML.NET支持机器学习和人工智能。5)异步编程和最佳实践提升了性能。

将C#.NET应用程序部署到Azure/AWS:逐步指南 将C#.NET应用程序部署到Azure/AWS:逐步指南 Apr 23, 2025 am 12:06 AM

如何将C#.NET应用部署到Azure或AWS?答案是使用AzureAppService和AWSElasticBeanstalk。1.在Azure上,使用AzureAppService和AzurePipelines自动化部署。2.在AWS上,使用AmazonElasticBeanstalk和AWSLambda实现部署和无服务器计算。

C#和.NET运行时:它们如何一起工作 C#和.NET运行时:它们如何一起工作 Apr 19, 2025 am 12:04 AM

C#和.NET运行时紧密合作,赋予开发者高效、强大且跨平台的开发能力。1)C#是一种类型安全且面向对象的编程语言,旨在与.NET框架无缝集成。2).NET运行时管理C#代码的执行,提供垃圾回收、类型安全等服务,确保高效和跨平台运行。

c#和.net:了解两者之间的关系 c#和.net:了解两者之间的关系 Apr 17, 2025 am 12:07 AM

C#和.NET的关系是密不可分的,但它们不是一回事。C#是一门编程语言,而.NET是一个开发平台。C#用于编写代码,编译成.NET的中间语言(IL),由.NET运行时(CLR)执行。

See all articles