例说C#深拷贝与浅拷贝
一开始,先对C#深拷贝与浅拷贝知识做个简单的总结。
无论是浅拷贝与深拷贝,C#都将源对象中的所有字段复制到新的对象中。不过,对于值类型字段,引用类型字段以及字符串类型字段的处理,两种拷贝方式存在一定的区别(见下表)。
下面给出完整的演示代码。
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary; namespace DeepCloneExp
{
class Program
{
static void Main(string[] args)
{
Person p = new Person() { Name="tiana0",Age=20,Job=new Job(){JobName="Coder"} }; Person p1 = p.ShallowClone();
Person p2 = p.DeepClone(); Console.WriteLine("p浅拷贝-->p1;p深拷贝-->p2"); Console.WriteLine("p修改前:p.Name={0},p.Age={1},p.Job.JobName={2}", p.Name, p.Age, p.Job.JobName);
Console.WriteLine("p修改前:p1.Name={0},p1.Age={1},p1.Job.JobName={2}", p1.Name, p1.Age, p1.Job.JobName);
Console.WriteLine("p修改前:p2.Name={0},p2.Age={1},p2.Job.JobName={2}", p2.Name, p2.Age, p2.Job.JobName); //修改p的所有字段值
p.Name = "tiana10000";
p.Age = 28;
p.Job.JobName = "Manager"; Console.WriteLine(); Console.WriteLine("p修改后:p.Name={0},p.Age={1},p.Job.JobName={2}", p.Name, p.Age, p.Job.JobName);
Console.WriteLine("p修改后:p1.Name={0},p1.Age={1},p1.Job.JobName={2}", p1.Name, p1.Age, p1.Job.JobName);
Console.WriteLine("p修改后:p2.Name={0},p2.Age={1},p2.Job.JobName={2}", p2.Name, p2.Age, p2.Job.JobName);
}
} [Serializable]
class Person:ICloneable
{
public int Age { get; set; } //值类型字段
public string Name { get; set; } //字符串
public Job Job { get; set; } //引用类型字段 //深拷贝
public Person DeepClone()
{
using (Stream objectStream = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(objectStream,this);
objectStream.Seek(0, SeekOrigin.Begin);
return formatter.Deserialize(objectStream) as Person;
}
} public object Clone()
{
return this.MemberwiseClone();
} //浅拷贝
public Person ShallowClone()
{
return this.Clone() as Person;
}
} [Serializable]
public class Job
{
public string JobName { get; set; }
public override string ToString()
{
return this.JobName;
}
}
}
运行程序,得到以下结果:
先来看看结果,很明显,当源对象改变时,副本只有浅拷贝这种情况下的引用类型字段的值会一起变化,与前面给出的结论一致(不记得的话,麻烦再看一下表格)。
对于演示代码,仅补充说明: Person 类与Job类均需添加标志[Serializable],否则运行时会报错。
好了,就扯到这里了。
例说C#深拷贝与浅拷贝的更多相关文章
- 设计模式_11_原型模式(prototype)深拷贝、浅拷贝
设计模式_11_原型模式(prototype) 浅拷贝: package designPatternOf23; /** * 定义:用原型实例,指定创建对象的种类,并通过拷贝这些原型创建新的对象 * P ...
- .net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的. ...
- 理解python可变类型vs不可变类型,深拷贝vs浅拷贝
核心提示: 可变类型 Vs 不可变类型 可变类型(mutable):列表,字典 不可变类型(unmutable):数字,字符串,元组 这里的可变不可变,是指内存中的那块内容(value)是否可以被改变 ...
- C++ Primer笔记9_构造函数_拷贝构造(深拷贝与浅拷贝)
1.构造函数: >构造函数是一个特殊的.与类同名的成员函数,用于给每一个成员设置适当的初始值. >构造函数不能有返回值,函数名与类名同样. >缺省构造函数时,系统将自己主动调用该缺省 ...
- java克隆之深拷贝与浅拷贝
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java深拷贝与浅拷贝实际项目中用的不多,但是对于理解Java中值传递,引用传递十分重要,同时个人认为对于理解内存模型也有帮助,况且面试中也是经常问 ...
- 从JS的深拷贝与浅拷贝到jq的$.extend()方法
一.堆内存与栈内存 堆和栈都是内存中划分出来的用来存储的区域,栈为自动分配的内存空间,它由系统自动释放,堆为动态分配的内存,大小不定也不会自动释放. 二.js基本数据类型与引用类型的不同 基本数据类型 ...
- 浅谈.net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的 ...
- iOS深拷贝与浅拷贝
概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 如图详解:
- 拷贝构造函数(深拷贝vs浅拷贝)
拷贝构造函数(深拷贝vs浅拷贝) 类对象之间的初始化是由类的拷贝构造函数完毕的.它是一种特殊的构造函数,它的作用是用一个已知的对象来初始化还有一个对象.假设在类中没有显式地声明一个拷贝构造函数.那么, ...
随机推荐
- UITabBarController 初学
纯代码编写UITabBarController, 不多说,直接见代码 RViewController1 *vc1 = [[RViewController1 alloc]init]; UINavigat ...
- .net开发---自定义页面打印区域
自定义页面打印区域 有3种办法: 办法一:将不需要打印的部位隐藏掉 Examp: <%-- (1)使用css样式,定义一个.noprint的class,将不打印的内容放入这个class内. -- ...
- _In_ 是什么意思
函数参数类型前 _In_代表什么 在visual C++中属于SAL批注,是为了编译系统在分析代码时发现缺陷用的 表示是一个输入参数.可以定义一个_In_的宏,这个宏什么都不做, 就是形如 ...
- JS七种加密解密方法
http://www.cnblogs.com/mq0036/p/4983858.html HTML或JS加密解密 本文一共介绍了七种方法: 一:最简单的加密解密 二:转义字符"\&q ...
- action方法不返回
当被请求的action方法中还有资源没有释放时,请求方法是不会返回的,会一直停留在方法中,即使是最后一行,因为请求方法一旦返回,那方法中的资源,引用就没有位置住了,所以所请求的方法会一直不返回,直到方 ...
- Find Minimum in Rotated Sorted Array问题的困惑
今天做了两题,第二题没解出来,发现太麻烦了,放弃了……明天脑子清楚的时候再做. 第一题就是标题中的这个问题.在一个旋转排序数组中找出最小的值. 针对该问题出了两道不同要求的题目,分别是不考虑重复元素的 ...
- 误删除了Oracle的dbf文件后的解决方法
问题描述: 误删除Oracle数据库的dbf文件,在启动和关闭数据库是会提示错误. startup启动数据库时提示: ORA-01157:无法标识/锁定数据文件 ORA-01110:数据文件:‘... ...
- iOS9 UITableViewCell separatorInset设置为0分割线还是没有顶到头的问题
只需要在自定义的Cell中添加以下代码即可 override func awakeFromNib() { super.awakeFromNib() layoutMargins = UIEdgeInse ...
- jdbc的封装
package com.wjf.helper; import java.io.FileInputStream; import java.io.FileOutputStream; import java ...
- 04_XML_01_入门基础
[什么是XML] Extensible Markup Language,翻译过来即可扩展标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 在XML语言中,它允 ...