如何在基类中创建对象的克隆?

我需要一个方法,在基类中创建一个对象的空克隆? 例如:

public class ChildClass : ParentClass { public ChildClass() { } } public class ParentClass { public SomeMethod() { // I want to create an instance of the ChildClass here } } 

到目前为止,我们在父类中定义了一个抽象方法。 并且,所有子类都实现它们。 但是,实现对所有人来说都是一样的,只是一种不同的类型。

 public class ChildClass : ParentClass { public ChildClass() { } public ParentClass CreateEmpty() { return new ChildClass(); } } public class ParentClass { public SomeMethod() { // I want to create an instance of the ChildClass here ParentClass empty = CreateEmpty(); } public abstract ParentClass CreateEmpty(); } 

有没有办法从父类中执行此操作,以便我不必为每个不同的子类继续实现相同的逻辑? 请注意,可能存在更多级别的inheritance(即ChildChildClass:ChildClass:ParentClass)。

如果使用reflection对您来说不是问题,您可以使用Activator类来完成:

 //In parent class public ParentClass CreateEmpty() { return (ParentClass)Activator.CreateInstance(this.GetType()); } 

这将返回所需类型的空对象。 请注意,此方法不需要是虚拟的。

另一方面,我认为您当前的方法非常好,几行代码并不是那么糟糕。

您可以使用二进制序列化器对对象进行深度克隆。

编辑:刚刚注意到克隆旁边的“空”这个词(我认为这是一个矛盾)。 无论如何都要保留此响应,希望它能帮助其他人找到这个问题,因为他们正在寻找定期克隆。

这有点实验性。 我不知道这是否会导致循环依赖。 几个月没碰过C#了。

 public class ParentClass where T : ParentClass, new() { // fixed public ParentClass() { var x = new T(); // fixed, was T.new() } } public class ChildClass : ParentClass { public ChildClass() { } } 

否则请去Ravadre的ReflectionCode。

我使用以下模式。

优点:

  • 这种模式确保了克隆在类的私有和公共方面的类型安全性。
  • 输出类将始终正确。
  • 你永远不会忘记覆盖“克隆”方法。 “MyDerivedClass”永远不会返回另一个类而不是“MyDerivedClass”。

缺点:

  • 对于一个类,您需要创建一个接口和两个类(原型和最终)

样品:

 // Common interface for cloneable classes. public interface IPrototype : ICloneable { new IPrototype Clone(); } // Generic interface for cloneable classes. // The 'TFinal' is finaly class (type) which should be cloned. public interface IPrototype where TFinal : IPrototype { new TFinal Clone(); } // Base class for cloneable classes. // The 'TFinal' is finaly class (type) which should be cloned. public abstract class PrototypeBase : IPrototype where TFinal : PrototypeBase { public TFinal Clone() { TFinal ret = this.CreateCloneInstance(); if ( null == ret ) { throw new InvalidOperationException( "Clone instance was not created." ); } this.FillCloneInstance( ret ); return ret; } // If overriden, creates new cloned instance protected abstract TFinal CreateCloneInstance(); // If overriden, fill clone instance with correct values. protected abstract void FillCloneInstance( TFinal clone ); IPrototype IPrototype.Clone() { return this.Clone(); } object ICloneable.Clone() { return this.Clone(); } } // Common interface for standalone class. public interface IMyStandaloneClass : IPrototype { string SomeText{get;set;} string SomeNumber{get;set;} } // The prototype class contains all functionality exception the clone instance creation. public abstract class MyStandaloneClassPrototype : PrototypeBase, IMyStandaloneClass where TFinal : MyStandaloneClassPrototype { public string SomeText {get; set;} public int SomeNumber {get; set} protected override FillCloneInstance( TFinal clone ) { // Now fill clone with values clone.SomeText = this.SomeText; clone.SomeNumber = this.SomeNumber; } } // The sealed clas contains only functionality for clone instance creation. public sealed class MyStandaloneClass : MyStandaloneClassPrototype { protected override MyStandaloneClass CreateCloneInstance() { return new MyStandaloneClass(); } } public interface IMyExtendedStandaloneClass : IMyStandaloneClass, IPrototype { DateTime SomeTime {get; set;} } // The extended prototype of MyStandaloneClassPrototype. public abstract class MyExtendedStandaloneClassPrototype : MyStandaloneClassPrototype where TFinal : MyExtendedStandaloneClassPrototype { public DateTime SomeTime {get; set;} protected override FillCloneInstance( TFinal clone ) { // at first, fill the base class members base.FillCloneInstance( clone ); // Now fill clone with values clone.SomeTime = this.SomeTime; } } public sealed class MyExtendedStandaloneClass : MyExtendedStandaloneClassPrototype { protected override MyExtendedStandaloneClass CreateCloneInstance() { return new MyExtendedStandaloneClass } }