2010-11-11 76 views
11

我有一个叫Employee的类,有3个属性叫做ID,NameDept。我需要执行CopyClone方法吗?当我使用CopyClone方法时,我需要避免Casting?我将如何做到这一点?如何在类中实现克隆和复制方法?

示例:与DataTable相同,其具有DataTable.Copy()DataTable.Clone()

回答

13

您需要实现IClonable接口并为克隆方法提供实现。 如果你想避免强制转换,请不要执行此操作。

一个简单的深度克隆方法可能是将对象序列化到内存然后反序列化它。您的类中使用的所有自定义数据类型都需要使用[Serializable]属性进行序列化。对于克隆,你可以使用类似

public MyClass Clone() 
    { 
     MemoryStream ms = new MemoryStream(); 
     BinaryFormatter bf = new BinaryFormatter(); 

     bf.Serialize(ms, this); 

     ms.Position = 0; 
     object obj = bf.Deserialize(ms); 
     ms.Close(); 

     return obj as MyClass; 
    } 

如果你的类只有value types,那么你可以使用一个copy constructor或只分配值在克隆方法的新对象。

+0

哇这是一个复杂的做法 - 为什么不只是使用复制构造函数? – 2010-11-11 09:05:51

+0

@Rowland它不适用于参考类型。无论如何编辑我的答案 – Midhat 2010-11-11 09:13:54

+1

@Rowland - 复制构造函数可能不会深层复制东西,并且需要在添加字段时进行维护。二进制序列化是进行深度复制的常用方式。 – 2010-11-11 09:13:58

2

检查这个克隆的对象在C#中使用IL http://whizzodev.blogspot.com/2008/03/object-cloning-using-il-in-c.html

+0

也只有浅拷贝,如果你需要深拷贝,你将不得不编辑IL生成器来递归地浏览图表。 – 2010-11-11 09:18:06

+0

还有更新的版本可用:http://whizzodev.blogspot.com/2008/06/object-deep-cloning-using-il-in-c_20.html – 2010-11-11 09:36:30

3

你必须使用ICloneable接口或者是不够的,如果你只是有两个方法称为CloneCopy是在一个通用的接口定义?

public class YourClass : ICloneable<YourClass> 
{ 
    // Constructor logic should be here 
    public YourClass Copy() { return this; }   
    public YourClass Clone() { return new YourClass(ID, Name, Dept); } 
} 

interface IClonable<T> 
{ 
    T Copy(); 
    T Clone(); 
} 

或者我误解了一些东西?

我想说的是,你不必让它变得比它更复杂?如果你需要你的对象符合某些你可以自己写的东西,如果在.Net框架中指定的那个要复杂的情况。您还应该定义与CloneCopy的区别,即它们对您意味着什么?我知道有几个网站指定Clone是深度复制,Copy是浅度复制。

+2

唯一的问题是维护开销。如果你添加一个新字段,你需要更新你的'CopyClone()'方法来合并它(以及它调用的构造函数)。如果你打算调用一个构造函数,而不是传递离散的字段,你应该传递整个对象,即:'返回new YourClass(this)' – 2010-11-11 09:16:00

+0

@Michael,这当然是正确的。但重要的是不要让它变得更复杂,直到你真的需要它。而复制方法可能是错误的(会改变它:))。你可能可以改变IClonable接口,我有一个抽象类,它包含一个Clone方法,该方法使用反射或Midhat在下面写的序列化模式。 – 2010-11-11 09:21:21

+0

甚至iam对差异文档感到困惑。现场?。 – 2010-11-11 10:10:04

3

你的意思是,如何实现ICloneable.Clone()并让它返回类本身的类型。

public class MyType : ICloneable 
{ 
    public MyType Clone() //called directly on MyType, returns MyType 
    { 
    return new MyType(/* class-dependant stuff goes here */); 
    } 
    object ICloneable.Clone() // called through ICloneable interface, returns object 
    { 
    return Clone(); 
    } 
} 
2

我经常看到复制构造函数被建议作为克隆方法的替代方法,但除了密封类以外,行为有很大不同。如果我有一个Type Car,它只支持属性VIN,BodyColor和BodyStyle,以及支持InteriorFabric和SoundSystem的派生类型FancyCar,那么接受Car类型对象并使用Car拷贝构造函数复制它的代码将结束与汽车。如果FancyCar被传递给这样的代码,则产生的“重复”将是新车,其具有匹配原车的VIN,BodyColor和BodyStyle,但不具有任何InteriorFabric或SoundSystem。相比之下,代码接受一个Car并在其上使用克隆方法,将FancyCar传递给代码将导致FancyCar被生成。

除非有人想使用Reflection,否则任何克隆方法都必须在其基础上调用base.MemberwiseClone。由于MemberwiseClone不是虚拟方法,因此我建议定义受保护的虚拟克隆方法;你也可以通过定义一个具有相同名称的保护范围的虚拟嵌套类来阻止任何子类调用MemberwiseClone(所以如果后代类试图调用base。MemberwiseClone,它不会被解释为对虚拟类的无意义引用)。

2

下面的例子:

namespace XXX 
{ 
    [Serializable] 
    public class ItemChecklist : ICloneable 
    { 

     // [...here properties, attributes, etc....] 



     object ICloneable.Clone() 
     { 
      return this.Clone(); 
     } 
     public ItemChecklist Clone() 
     { 
      return (ItemChecklist)this.MemberwiseClone(); 
     } 


    } 
} 

即如果使用此功能,您将在“itemAdd”对象“itemTemp”以其所有值的完整副本。

ItemChecklist itemAdd = itemTemp.Clone();