C#通过序列化实现深拷贝

关于浅拷贝深拷贝,我的理解不是很清晰,简单说来,我认为是这样子:

  浅拷贝:引用成员在被拷贝时仅复制源对象中引用成员的地址到新对象中,所以在新对象中对引用成员进行更改会影响到源对象(除对引用成员进行赋值外)。

  深拷贝:引用成员在拷贝时新建一个引用对象到新对象中,且将源对象中引用对象的成员值复制到新对象的引用对象中,所以在新对象中对引用成员进行更改不会影响源对象。

  说起来概念也简单,我想大家纠结的是如何实现深拷贝?浅拷贝的实现很简单,调用Object.MemberwiseClone就万事大吉了。在网上找了一个通过序列化实现深拷贝的例子,自己改了改,欢迎大家品头论足。

  这段程序的输出为:

  objA1.RefClass.Field = 10
  objA2.RefClass.Field = 10
  objA1.RefClass.Field = 10
  objA2.RefClass.Field = 30
  objB1.RefClass.Field = 20
  objB2.RefClass.Field = 10  

  要注意的是,本例中实现深拷贝的ClassB类及其引用成员RefClass类必须添加Serializable特性。


using System;

using System.Collections;

using System.Collections.Generic;

using System.Text;

using System.IO;

using System.Runtime.Serialization.Formatters.Binary;

namespace ConsoleApplication1

{

//被引用类,必须添加Serializable特性,否则不能实现序列化

[Serializable]

class RefClass

{

private int field;

public int Field

{

get { return field; }

set { this.field = value; }

}

}

//浅拷贝示例

class ClassA : ICloneable

{

private RefClass refClass;

public RefClass RefClass

{

get { return refClass; }

set { refClass = value; }

}

public ClassA()

{

refClass = new RefClass();

}

public object Clone()

{

//调用MemberwiseClone实现浅拷贝

return MemberwiseClone();

}

}

//深拷贝示例,必须添加Serializable特性,否则不能实现序列化

[Serializable]

class ClassB : ICloneable

{

private RefClass refClass;

public RefClass RefClass

{

get { return refClass; }

}

public ClassB()

{

refClass = new RefClass();

}

//深拷贝

public object Clone()

{

//创建内存流

MemoryStream ms = new MemoryStream();

//以二进制格式进行序列化

BinaryFormatter bf = new BinaryFormatter();

bf.Serialize(ms, this);

//反序列化当前实例到一个object

ms.Seek(0, 0);

object obj = bf.Deserialize(ms);

//关闭内存流

ms.Close();

return obj;

}

}

class Program

{

static void Main(string[] args)

{

//浅拷贝

ClassA objA1 = new ClassA();

objA1.RefClass.Field = 20;

ClassA objA2 = (ClassA)objA1.Clone();

//在新对象中修改RefClass的Field值,源对象中的值亦更改

objA2.RefClass.Field = 10;

Console.WriteLine("objA1.RefClass.Field = " + objA1.RefClass.Field.ToString());

Console.WriteLine("objA2.RefClass.Field = " + objA2.RefClass.Field.ToString());

//对新对象中的RefClass重新进行赋值操作,不影响源对象

objA2.RefClass = new RefClass();

objA2.RefClass.Field = 30;

Console.WriteLine("objA1.RefClass.Field = " + objA1.RefClass.Field.ToString());

Console.WriteLine("objA2.RefClass.Field = " + objA2.RefClass.Field.ToString());

//深拷贝

ClassB objB1 = new ClassB();

objB1.RefClass.Field = 20;

ClassB objB2 = (ClassB)objB1.Clone();

//在新对象中修改RefClass的Field值,源对象中的值不变

objB2.RefClass.Field = 10;

Console.WriteLine("objB1.RefClass.Field = " + objB1.RefClass.Field.ToString());

Console.WriteLine("objB2.RefClass.Field = " + objB2.RefClass.Field.ToString());

Console.ReadKey();

}

}

}

时间: 2024-09-21 06:59:31

C#通过序列化实现深拷贝的相关文章

java 深拷贝探讨

java 深拷贝探讨 本文将讨论以下4个问题 1. java Cloneable接口实现深拷贝 2. java 序列化实现深拷贝 3. 号称最快的深拷贝二方库cloning源码分析 4. 几种拷贝方式速度的比较 深拷贝的概念本文就不说了.在C++中实现深拷贝一般情况下重载赋值操作符 "=" 来实现同一个类的对象间的深拷贝,所以很自然的在java中我们也同样可以定义一个copy函数,在函数内部为对象的每一个属性作赋值操作.这种方式简单自然,但存在一个致命性的问题:如果有一天在类中新增加了

Java中的深拷贝和浅拷贝介绍_java

一.引言   对象拷贝(Object Copy)就是将一个对象的属性拷贝到另一个有着相同类类型的对象中去.在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复用对象的部分或全部 数据.Java中有三种类型的对象拷贝:浅拷贝(Shallow Copy).深拷贝(Deep Copy).延迟拷贝(Lazy Copy). 二.浅拷贝 1.什么是浅拷贝   浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝.如果属性是基本类型,拷贝的就是基本类型的值:如果属性是内存地

探讨java深拷贝_java

本文将讨论以下4个问题     1. java Cloneable接口实现深拷贝     2. java 序列化实现深拷贝     3. 号称最快的深拷贝二方库cloning源码分析     4. 几种拷贝方式速度的比较 深拷贝的概念本文就不说了.在C++中实现深拷贝一般情况下重载赋值操作符 "=" 来实现同一个类的对象间的深拷贝,所以很自然的在java中我们也同样可以定义一个copy函数,在函数内部为对象的每一个属性作赋值操作.这种方式简单自然,但存在一个致命性的问题:如果有一天在类

java对象拷贝

java赋值是复制对象引用,如果我们想要得到一个对象的副本,使用赋值操作是无法达到目的的: @Test public void testassign(){ Person p1=new Person(); p1.setAge(31); p1.setName("Peter"); Person p2=p1; System.out.println(p1==p2);//true } 如果创建一个对象的新的副本,也就是说他们的初始状态完全一样,但以后可以改变各自的状态,而互不影响,就需要用到jav

.NET设计模式-原型模式(Prototype Pattern)

原型模式(Prototype Pattern) --.NET设计模式系列之六 Terrylee,2006年1月 概述 在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构.这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适.那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化? 意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 结构图 Prototype模式结构图 生活中的例子 Pr

艾伟_转载:.NET设计模式:原型模式(Prototype Pattern)

概述 在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构.这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适.那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化? 意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 结构图 Prototype模式结构图 生活中的例子 Prototype模式使用原型实例指定创建对象的种类.新产品的原型通常是先于全部产品建立的,这样的原型是被动的,并不

Head First设计模式之备忘录模式

一.定义 不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样就可以将该对象恢复到原先保存的状态 二.结构 备忘录模式中主要有三类角色: 发起人角色:记录当前时刻的内部状态,负责创建和恢复备忘录数据. 备忘录角色:负责存储发起人对象的内部状态,在进行恢复时提供给发起人需要的状态. 管理者角色:负责保存备忘录对象,但是不能对备忘录对象的内容进行操作或检查. 三.适用场景 1.需要保存/恢复数据的相关状态场景. 2.提供一个可回滚的操作. 四.优缺点 优点:  1.给用户提

.NET设计模式:原型模式(Prototype Pattern)

概述 在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构.这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适.那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化? 意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 结构图 Prototype模式结构图 生活中的例子 Prototype模式使用原型实例指定创建对象的种类.新产品的原型通常是先于全部产品建立的,这样的原型是被动的,并不

C#对象的浅拷贝,深拷贝及利用序列化等多种方式实现深拷贝

C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量,对于值类型变量,深拷贝和前拷贝都是通过赋值操作符号(=)实现,其效果一致,将对象中的值类型的字段拷贝到新的对象中.这个很容易理解. 本文重点讨论引用类型变量的拷贝机制和实现. C#中引用类型对象的copy操作有两种: 浅拷贝(影子克隆/shallow copy):只复制对象的值类型字段,对象的引用类型,仍属于原来的引用. 深拷贝(深度克隆):不仅复制对象的值类型字段,同时也复制原对象中的对象.就是说完全是新对象产生的. 浅拷贝和深拷贝