Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to implement ICloneable

What is the proper way of implementing ICloneable in a class hierarchy? Say I have an abstract class DrawingObject. Another abstract class RectangularObject inherits from DrawingObject. Then there are multiple concrete classes like Shape, Text, Circle etc. that all inherit from RectangularObject. I want to implement ICloneable on DrawingObject and then carry it down the hierarchy, copying available properties at each level and calling parent's Clone at the next level.

The problem however is that since the first two classes are abstract, I cannot create their objects in the Clone() method. Thus I must duplicate the property-copying procedure in each concrete class. Or is there a better way?

like image 463
dotNET Avatar asked Jan 14 '14 14:01

dotNET


People also ask

How to implement ICloneable in c#?

Notes to Implementers The ICloneable interface simply requires that your implementation of the Clone() method return a copy of the current object instance. It does not specify whether the cloning operation performs a deep copy, a shallow copy, or something in between.

Should I use ICloneable?

You shouldn't. Microsoft recommends against implementing ICloneable because there's no clear indication from the interface whether your Clone method performs a "deep" or "shallow" clone.


1 Answers

You can easily create a superficial clone with object's protected method MemberwiseClone.

Example:

   public abstract class AbstractCloneable : ICloneable    {       public object Clone()       {          return this.MemberwiseClone();       }    } 

If you don't need anything like a deep copy, you will not have to do anything in the child classes.

The MemberwiseClone method creates a shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object. If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.

If you need more intelligence in the cloning logic, you can add a virtual method to handle references :

   public abstract class AbstractCloneable : ICloneable    {       public object Clone()       {          var clone = (AbstractCloneable) this.MemberwiseClone();          HandleCloned(clone);          return clone;       }        protected virtual void HandleCloned(AbstractCloneable clone)       {          //Nothing particular in the base class, but maybe useful for children.          //Not abstract so children may not implement this if they don't need to.       }    }      public class ConcreteCloneable : AbstractCloneable    {        protected override void HandleCloned(AbstractCloneable clone)        {            //Get whathever magic a base class could have implemented.            base.HandleCloned(clone);             //Clone is of the current type.            ConcreteCloneable obj = (ConcreteCloneable) clone;             //Here you have a superficial copy of "this". You can do whathever             //specific task you need to do.            //e.g.:            obj.SomeReferencedProperty = this.SomeReferencedProperty.Clone();        }    } 
like image 188
Johnny5 Avatar answered Sep 22 '22 05:09

Johnny5