How to create an object cloning in a base class?

Do I need a method that creates an empty clone of an object in a base class? For example:

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

So far, we have an abstract method defined in the parent class. And all child classes implement them. But the implementation is the same for everyone, just for a different type.

 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(); } 

Is there a way to do this from the parent class so that I don't have to execute the same logic for every other child class? Note that there may be more levels of inheritance (e.g. ChildChildClass: ChildClass: ParentClass).

+1
source share
4 answers

If using reflection is not a problem for you, you can do this with the Activator class:

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

This returns an empty object of the type you want. Please note that this method does not have to be virtual.

On the other hand, I think your current approach is perfectly fine, a few more lines of code are not so bad.

+5
source

This is somewhat experimental. I do not know if this will lead to cyclical dependence. Do not touch C # for several months.

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

Otherwise, go to ReflectionCode by Ravadre.

0
source

You can make a deep clone of an object using a binary serializer .

EDIT: Just noticed the word “empty” next to the clone (which I thought was an oxymoron). Leaving this answer one way or another hoping that it will help others who find this question because they want to make an ordinary clone.

0
source

I am using the following pattern.

Pros:

  • This template protects the type of cloning security on the private and public sides of classes.
  • The output class will always be correct.
  • You never forgot to override the clone method. "MyDerivedClass" never returns a class other than "MyDerivedClass".

Minuses:

  • For one class, you need to create one interface and two classes (prototype and final)

Example:

 // 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<TFinal> where TFinal : IPrototype<TFinal> { new TFinal Clone(); } // Base class for cloneable classes. // The 'TFinal' is finaly class (type) which should be cloned. public abstract class PrototypeBase<TFinal> : IPrototype<TFinal> where TFinal : PrototypeBase<TFinal> { 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<IMyStandaloneClass> { string SomeText{get;set;} string SomeNumber{get;set;} } // The prototype class contains all functionality exception the clone instance creation. public abstract class MyStandaloneClassPrototype<TFinal> : PrototypeBase<TFinal>, IMyStandaloneClass where TFinal : MyStandaloneClassPrototype<TFinal> { 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<MyStandaloneClass> { protected override MyStandaloneClass CreateCloneInstance() { return new MyStandaloneClass(); } } public interface IMyExtendedStandaloneClass : IMyStandaloneClass, IPrototype<IMyExtendedStandaloneClass> { DateTime SomeTime {get; set;} } // The extended prototype of MyStandaloneClassPrototype<TFinal>. public abstract class MyExtendedStandaloneClassPrototype<TFinal> : MyStandaloneClassPrototype<TFinal> where TFinal : MyExtendedStandaloneClassPrototype<TFinal> { 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<TFinal> { protected override MyExtendedStandaloneClass CreateCloneInstance() { return new MyExtendedStandaloneClass } } 
0
source

All Articles