C#之Clone
来源:互联网 发布:服务器怎么绑定域名 编辑:程序博客网 时间:2024/05/22 18:50
MemberwiseClone 方法创建一个浅表副本,具体来说就是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。
为了实现深度复制,我们就必须遍历有相互引用的对象构成的图,并需要处理其中的循环引用结构。这无疑是十分复杂的。幸好借助.Net的序列化和反序列化机制,可以十分简单的深度Clone一个对象。原理很简单,首先将对象序列化到内存流中,此时对象和对象引用的所用对象的状态都被保存到内存中。.Net的序列化机制会自动处理循环引用的情况。然后将内存流中的状态信息反序列化到一个新的对象中。这样一个对象的深度复制就完成了。在原型设计模式中CLONE技术非常关键。
下面的代码就是演示这个问题:
using System;using System.IO;using System.Runtime.Serialization.Formatters.Binary;namespace CloneDemo{ [Serializable] class DemoClass { public int i = 0; public int[] iArr = { 1, 2, 3 }; public DemoClass Clone1() //浅CLONE { return this.MemberwiseClone() as DemoClass; } public DemoClass Clone2() //深clone { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Position = 0; return formatter.Deserialize(stream) as DemoClass; } } class Program { static void Main(string[] args) { DemoClass a = new DemoClass(); a.i = 10; a.iArr = new int[] { 8, 9, 10 }; DemoClass b = a.Clone1(); DemoClass c = a.Clone2(); // 更改 a 对象的iArr[0], 导致 b 对象的iArr[0] 也发生了变化 而 c不会变化 a.iArr[0] = 88; Console.WriteLine("MemberwiseClone"); Console.WriteLine(b.i); foreach (var item in b.iArr) { Console.WriteLine(item); } Console.WriteLine("Clone2"); Console.WriteLine(c.i); foreach (var item in c.iArr) { Console.WriteLine(item); } Console.ReadLine(); } }}
另外一个例子是针对数组,C#中的数组是引用型的变量,我们通过数组来进行演示:
浅拷贝:
using System;
class ShallowCopy : ICloneable
{
public int[] v = {1,2,3};
public Object Clone()
{
return this.MemberwiseClone();
}
public void Display()
{
foreach(int i in v)
Console.Write( i + ", ");
Console.WriteLine();
}
}
class Client
{
public static void Main()
{
ShallowCopy sc1 = new ShallowCopy();
ShallowCopy sc2 = (ShallowCopy)sc1.Clone();
sc1.v[0] = 9;
sc1.Display();
sc2.Display();
}
}
ShallowCopy对象实现了一个浅拷贝,因此当对sc1进行克隆时,其字段v并没有克隆,这导致sc1与sc2的字段v都指向了同一个v,因此,当修改了sc1的v[0]后,sc2的v[0]也发生了变化。
深拷贝:
using System;
class DeepCopy : ICloneable
{
public int[] v = {1,2,3};
// 默认构造函数
public DeepCopy()
{
}
// 供Clone方法调用的私有构造函数
private DeepCopy(int[] v)
{
this.v = (int[])v.Clone();
}
public Object Clone()
{
// 构造一个新的DeepCopy对象,构造参数为
// 原有对象中使用的 v
return new DeepCopy(this.v);
}
public void Display()
{
foreach(int i in v)
Console.Write( i + ", ");
Console.WriteLine();
}
}
class Client
{
public static void Main()
{
DeepCopy dc1 = new DeepCopy();
DeepCopy dc2 = (DeepCopy)dc1.Clone();
dc1.v[0] = 9;
dc1.Display();
dc2.Display();
}
}
这次在克隆的时候,不但克隆对象本身,连里面的数组字段一并克隆。因此,最终打印出来的dc1与dc2不同。
当然我们也可以建个深拷贝的帮助类:
public static class ObjectCopier{ /// <summary> /// Perform a deep Copy of the object. /// </summary> /// <typeparam name="T">The type of object being copied.</typeparam> /// <param name="source">The object instance to copy.</param> /// <returns>The copied object.</returns> public static T Clone<T>(T source) { if (!typeof(T).IsSerializable) { throw new ArgumentException("The type must be serializable.", "source"); } // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } IFormatter formatter = new BinaryFormatter(); Stream stream = new MemoryStream(); using (stream) { formatter.Serialize(stream, source); stream.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(stream); } }}
- C#之Clone
- C#之MemberwiseClone与Clone
- C#之MemberwiseClone与Clone
- C#之MemberwiseClone与Clone
- C# 之 类复制 MemberwiseClone与Clone(深 浅 Clone)
- C# 之 类复制 MemberwiseClone与Clone(深 浅 Clone)
- C# 之 类复制 MemberwiseClone与Clone(深 浅 Clone)
- C# Clone()
- C# clone
- [转]C# 之 类复制 MemberwiseClone与Clone(深 浅 Clone)
- C# Clone() 方法
- C# Clone() 方法
- Java 之 clone 分析
- java学习之clone
- leetcode之Clone Graph
- leetcode之Clone Graph
- leetcode之Clone Graph
- java object之clone
- 《泰囧》的票房是如何成功运营的
- ligerCombox 的用法
- Android学习笔记(20)————利用ListView制作带竖线的多彩表格
- virtualbox apache mysql php环境搭建
- 把程序打包成APK
- C#之Clone
- 我的emacs23配置文件--用于方便git上传代码
- InnoDB和MyISAM区别
- 上传文件动态设置enctype
- android 绘制
- matlab中mex与c混合编程总结
- oracle 自动备份
- Lucene学习笔记(一)——入门示例
- POJ 2465 Adventures in Moving - Part IV