`
tubaluer
  • 浏览: 1454933 次
文章分类
社区版块
存档分类
最新评论
  • sblig: c / c++ 是不一样的都会输出 100
    j = j++

利用对象序列化深表克隆对象

 
阅读更多

在.NET上,一切都是对象。这种安排的后果之一就是在当将一个变量赋值给另一个变量的时候,会得到两个指向同一对象的变量,而不是两个不同的数据副本(除非是使用值类型而不是引用类型)。一般情况下,可以通过调用类所公开的一个特殊方法得到一个数据的副本。在.NET世界中,类应当实现ICloneable接口并公开这个接口的惟一方法Clone,让外部调用知道它能够创建类的实例的副本。框架中有多个对象可以实现这个接口,包括Array、ArrayList、BitArray、Font、Icon、Queue和Stack。

大多数的时候,实现ICloneable接口都相当的简单。所有其他类都是从System.Object 类继承来的。该类所定义的MemberwiseClone方法可以帮助复制对象,而无需手动复制对象的各个属性:

// Implements ICloneable.Clone 方法。

public object Clone()

{

// 对象属性如果是复杂类型,那么创建的仍然是其浅表副本。

//对象属性如果是复杂类型,那么复制仍然需要手动。

//只是利用MemberwiseClone复制所有的非对象值。

return this.MemberwiseClone();

}

但是,这种方法使我们使用时感到不爽,因为,只有通过更改对象定义的源代码才可以克隆一个对象,因为MemberwiseClone方法是受保护的,它只有在类的内部才可以被访问。还有,也是在多数情况下更为重要的一个方面,MemberwiseClone方法执行的是对象的浅表复制——也就是说,它创建了对象的一个副本,但是没有创建该对象所引用的其他任何对象的副本。(就是说,对象内部的数据成员如果是引用的话,还是得我们手动复制的,如果对象图非常复杂,那么我们所面对的工作是多么的繁杂,嗷嗷不爽。)

使用对象序列化来处理复杂的对象图可以同时解决前面所提到的两个问题。实际上,可以创建一个通用的方法来对任何对象进行深表克隆。

这是一个简单的提供序列化克隆对象方法:

public static object CloneObject(object obj)
{

// 创建内存流
using(System.IO.MemoryStream ms = new MemoryStream(1000))
{
object CloneObject;

// 创建序列化器(有的书称为串行器)

// 创建一个新的序列化器对象总是比较慢。
BinaryFormatter bf = new BinaryFormatter(null,
new StreamingContext(StreamingContextStates.Clone));
// 将对象序列化至流

bf.Serialize(ms, obj);

// 将流指针指向第一个字符

ms.Seek(0, SeekOrigin.Begin);

// 反序列化至另一个对象(即创建了一个原对象的深表副本)

CloneObject = bf.Deserialize(ms);

// 关闭流
ms.Close();
return CloneObject;
}
}

以下,是一个使用这个方法克隆的例子:

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

namespace ObjectCloneBySerialize
{

class Class1
{

[STAThread]
static void Main(string[] args)
{
ArrayList Persons = new ArrayList();
Person Fangxing = new Person("Fang Xing", "Male");
Persons.Add(Fangxing);
Person Liwei = new Person("Li Wei", "Male");
Persons.Add(Liwei);

ArrayList ClonedPersons = (ArrayList)CloneObject(Persons);
Person Zhangsan = new Person("Zhang San", "Male");
ClonedPersons.Add(Zhangsan);

Console.WriteLine("===== Before Clone =====");
for(int i=0; i<Persons.Count; i++)
{
Person someone = (Person)Persons[i];
Console.WriteLine(someone.Name + " " + someone.Gender);
}

Console.WriteLine("===== After Clone =====");
for(int i=0; i<ClonedPersons.Count; i++)
{
Person someone = (Person)ClonedPersons[i];
Console.WriteLine(someone.Name + " " + someone.Gender);
}

Console.ReadLine();

}

public static object CloneObject(object obj)
{
using(System.IO.MemoryStream ms = new MemoryStream(1000))
{
object CloneObject;
BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
bf.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
CloneObject = bf.Deserialize(ms);
ms.Close();
return CloneObject;
}
}
}

[Serializable]
class Person
{
private string m_Name;
private string m_Gender;

public string Name
{
get{return m_Name;}
}

public string Gender
{
get{return m_Gender;}
}

public Person(string name, string gender)
{
m_Name = name;
m_Gender = gender;
}

}
}

分享到:
评论

相关推荐

    Java经典编程源码基础例程300.zip

    实例057 序列化与对象克隆 84 实例058 深克隆效率的比较 87 第7章 面向对象进阶 89 实例059 经理与员工的差异 90 实例060 重写父类中的方法 92 实例061 计算几何图形的面积 93 实例062 简单的汽车销售商场 95 实例...

    C++MFC教程

    |------ 3.5 利用序列化进行文件读写 |------ 3.6 MFC中所提供的各种视类介绍 +-- 第四章 窗口控件 |------ 4.1 Button |------ 4.2 Static Box |------ 4.3 Edit Box |------ 4.4 Scroll Bar |------ 4.5 List Box/...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例112 序列化与对象克隆 139 实例113 深克隆效率的比较 141 实例114 transient关键字的应用 143 5.7 接口和内部类 145 实例115 使用sort()方法排序 145 实例116 简化compareTo()方法的重写 146 实例117 策略模式的...

    asp.net知识库

    泛型的序列化问题 .NET 2.0 泛型在实际开发中的一次小应用 C#2.0 Singleton 的实现 .Net Framwork 强类型设计实践 通过反射调用類的方法,屬性,字段,索引器(2種方法) ASP.NET: State Server Gems 完整的动态加载/卸载...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    其二、技术层次深:如果期望进入IT服务或者产品公司(类似毕博、DELL、IBM等),Oracle技术能够帮助提高就业的深度。 其三、职业方向多:Oracle数据库管理方向、Oracle开发及系统架构方向、Oracle数据建模数据仓库等...

    计算机二级C语言考试题预测

    作者:天使~之戀 已被分享1次 评论(0) 复制链接 分享 转载 删除 下面的138道题目,在二级考试中命中率极高。 一、选择题 (1) 下面叙述正确的是(C) A. 算法的执行效率与数据的存储结构无关 B. 算法的空间复杂度是指...

    用c描述的数据结构演示软件

    图示窗口的上方显示已知广义表的存储结构,图示窗口的下方显示复制求得的广义表的存储结构。递归工作栈中含调用语句行号 adr、变参 nls 和值参 ls。 15. 创建广义表的存储结构 图示窗口显示广义表存储结构的建立...

    数据结构演示软件

    图示窗口的上方显示已知广义表的存储结构,图示窗口的下方显示复制求得的广义表的存储结构。递归工作栈中含调用语句行号 adr、变参 nls 和值参 ls。 15. 创建广义表的存储结构 图示窗口显示广义表存储结构的建立...

    C#微软培训资料

    第七章 表 达 式 .58 7.1 操 作 符 .58 7.2 算术操作符和算术表达式.59 7.3 赋值操作符和赋值表达式.64 7.4 关系操作符和关系表达式.65 &lt;&lt;page 2&gt;&gt; page begin==================== 7.5 逻辑操作符和...

    .net技术资料大全(语言规范 源码教程 学习笔记 技术资料 .net代码生成器)

    DataSet对象.txt DotNET WinForm FAQ 16个.txt excel打印.txt EXCEL导出.txt EXCEL中合并单元格.txt mail.txt NET在RichTextBox控件加入图片(类似QQ).txt send.txt SQL储存过程等的解密.txt VisualC#打造...

    ASP升级.net资料大全(c#入门 语言规范 源码教程 学习笔记 技术资料 面试题 asp与.net代码生成器)

    DataSet对象.txt DotNET WinForm FAQ 16个.txt excel打印.txt EXCEL导出.txt EXCEL中合并单元格.txt mail.txt NET在RichTextBox控件加入图片(类似QQ).txt send.txt SQL储存过程等的解密.txt VisualC#打造...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    东南大学、中国科学技术信息研究所、国家图书馆有权保留本人所送交学位论文的复印件和电子文档,可以采用影印、缩印或其他复制手段保存论文。本人电子文档的内容和纸质论文的内容相一致。除在保密期内的保密论文和在...

    入门学习Linux常用必会60个命令实例详解doc/txt

    在使用mount这个指令时,至少要先知道下列三种信息:要加载对象的文件系统类型、要加载对象的设备名称及要将设备加载到哪个目录下。 (1)Linux可以识别的文件系统 ◆ Windows 95/98常用的FAT 32文件系统:vfat ;...

Global site tag (gtag.js) - Google Analytics