本篇文章为大家展示了深入浅析c#中的克隆方法,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
克隆方法是原型设计模式中必须使用的方式,它将返回一个与当前对象数据一致的对象,正如其名,犹如一个模子雕刻而出。克隆类型分为两种:浅克隆,深克隆。
<强> 1,浅克隆
强>
浅克隆方式是最简单,最直接的方式,只需要类实现接口ICloneable(在命名空间System.Runtime.InteropServices下)的克隆方法,在方法中使用加入对当前类的MemberwiseClone()方法即可。在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象,如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象。
如:
公共类学生:ICloneable {///& lt; summary>///值类型///& lt;/summary> 公共int ID{得到;设置;}///& lt; summary>///引用类型///& lt;/summary> 公共对象obj{得到;设置;} 公共对象克隆() { 返回this.MemberwiseClone (); } }
以上方法实现了对类对象的浅克隆方式。但是在该类中具有引用类型字段,浅克隆方法无法对引用字段进行克隆,引用字段仅仅是对其进行了地址引用,所以,当修改原本或者副本的引用字段的数据时,另一个对象的引用对象的数据同样会变化。深克隆将有效的解决此问题。
<强> 2,深克隆强>
深克隆相对于浅克隆方式比较复杂。深克隆是无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。
深克隆实现的机制是将对象进行序列化为数据后,再次将数据反序列化为新的对象。序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。注意,在实现序列化前需要在类的上方标记为可序列化。本文采用的序列化方式为二进制序列化。
主要实现的代码如下:
(序列化)//标记特性:可序列化 公开课的学生 {///& lt; summary>///值类型///& lt;/summary> 公共int ID{得到;设置;}///& lt; summary>///引用类型///& lt;/summary> 公共对象obj{得到;设置;} 公开学生克隆() { 学生克?new (); 使用(流流=new MemoryStream ()) { IFormatter格式化程序=new BinaryFormatter (); 试一试 { 格式化程序。序列化(流); 流。寻求(0,SeekOrigin.Begin); 克?formatter.Deserialize(流)的学生; } 抓住(SerializationException e) { Console.WriteLine(“未能序列化。原因是:“+ e.Message); 扔; } } 返回克隆; } }
深克隆实现机制相对复杂、效率稍慢,但它克服了浅克隆方式的不足,使得克隆对象时将类中的引用类型数据完全克隆为新的对象,而不是引用原本中的对象。如此,在修改双方的引用类型对象的数据时不会对另一方造成干扰。
但为每一个类都实现克隆方式,而重复书写相同代码未免麻烦。因此引入泛型方法。
<强> 3,泛型方法实现克隆强>
泛型的出现使得可以良好的解决在多个类或结构体中都需要进行克隆时重复编写代码的麻烦。在外部只需要使用相关方法即可。其代码如下:
///& lt;参数name=皌"祝辞& lt;/param>///& lt; returns> & lt;/returns> 公共静态T DepthCloneT (T) { T克?违约(T); 使用(流流=new MemoryStream ()) { IFormatter格式化程序=new BinaryFormatter (); 试一试 { 格式化程序。序列化(流,t); 流。寻求(0,SeekOrigin.Begin); 克?(T) formatter.Deserialize(流); } 抓住(SerializationException e) { Console.WriteLine(“未能序列化。原因是:“+ e.Message); 扔; } } 返回克隆; } }
在外部使用的方法如下: