locked
How to override the clone method? RRS feed

  • Question

  • Lets say I have a class with a Clone() method in it that looks something like this:

    public virtual object Clone()
            {
                return new Output(){
                    Property1 = this.Property1,
                    Property2 = this.Property2,
                    Property3 = this.Property3,
                    Property4 = this.Property4
                };
            }
    Now in my derived class I want to override the Clone() method, but I don't want to assign to these four properties in it. I have tried something like this with no luck.

    public override object Clone()
            {
                 ThisClass test = base.Clone() as ThisClass;
                 
                 test.ThisClassProperty1 = this.ThisClassProperty1,
                 test.ThisClassProperty2 = this.ThisClassProperty2
    
    }
    However this statement always returns null: ThisClass test = base.Clone() as ThisClass;

    How do you override the clone method?
    Friday, February 26, 2010 8:38 PM

Answers

  • Use the Copy Constructor pattern for cloning.  Each class is responsible for cloning its contents through a dedicated constructor.


    class BaseClass
    {
        public BaseClass()  { }
    
        protected BaseClass(BaseClass copy)
        {
            this.Property1 = copy.Property1;
        }
    
        public Property1 { get; set; }
    
        public virtual object Clone()
        {
            return new BaseClass(this);
        }
    }
    
    class SubClass : BaseClass
    {
        public SubClass()  { }
    
        protected SubClass(SubClass copy) 
            : base(copy)  
        {
            this.Property2 = copy.Property2;
        }
    
        public Property2 { get; set; }
    
        public override object Clone()
        {
            return new SubClass(this);
        }
    
    }


    /Calle
    - Still confused, but on a higher level -
    • Proposed as answer by Louis.fr Saturday, February 27, 2010 4:36 PM
    • Marked as answer by Ji.Zhou Saturday, March 6, 2010 5:30 AM
    Friday, February 26, 2010 10:02 PM
  • You can do like
    using System;
    using System.Threading;
    using System.Collections.Generic;
    
    class MainEntry
    {
        static void Main(string[] args)
        {
            ThisClass tc = new ThisClass() { Property1 = 1, Property2 = "2", Property3 = 3.0F, Property4 = "four" };
            object o = tc.Clone();
        }
        class Output : ICloneable
        {
            public object Property1 { set; get; }
            public object Property2 { set; get; }
            public object Property3 { set; get; }
    
            #region ICloneable Members
    
            public virtual object Clone()
            {
                return new Output() { Property1 = this.Property1, Property2 = this.Property2, Property3 = this.Property3 };
            }
    
            #endregion
        }
        class ThisClass : Output
        {
            public object Property4 { set; get; }
            public override object Clone()
            {
                Output op = base.Clone() as Output;
                return new ThisClass() { Property1 = op.Property1, Property2 = op.Property2, Property3 = op.Property3, Property4 = this.Property4 };
            }
        }
    }
    

    My Blog - MSDN Complement by providing Visual C# Walkthroughs and Sample Codes - Founded In February 24, 2010
    • Marked as answer by Ji.Zhou Saturday, March 6, 2010 5:29 AM
    Saturday, February 27, 2010 7:45 AM

All replies

  • Unfortunately, cloning is difficult and error prone.  You normally have to implement all of the base class properties, as well.

    The alternative is to break "Clone" up into multiple virtual methods:


    public class MyClass
    {
        public MyClass Clone()
        {
            MyClass newObject = ConstructObject();
            CopyPropertiesTo(newObjects);
        }
    
        protected virtual MyClass ConstructObject()
        {
            return new MyClass();
        }
    
        protected virtual void CopyPropertiesTo(MyClass other)
        {
            other.Property1 = this.Property1;
            // .. other
        }
    }
    
    public class Subclass : MyClass
    {
        protected override MyClass ConstructObject()
        {
             return new Subclass();
        }
    
        protected override void CopyPropertiesTo(MyClass other)
        {
               base.CopyPropertiesTo(other);
               Subclass newClass = other as Subclass;
               if (newClass) {
                    newClass.Property5 = this.Property5;
               }
        }
    }


    Reed Copsey, Jr. - http://reedcopsey.com
    Friday, February 26, 2010 8:50 PM
  • Use the Copy Constructor pattern for cloning.  Each class is responsible for cloning its contents through a dedicated constructor.


    class BaseClass
    {
        public BaseClass()  { }
    
        protected BaseClass(BaseClass copy)
        {
            this.Property1 = copy.Property1;
        }
    
        public Property1 { get; set; }
    
        public virtual object Clone()
        {
            return new BaseClass(this);
        }
    }
    
    class SubClass : BaseClass
    {
        public SubClass()  { }
    
        protected SubClass(SubClass copy) 
            : base(copy)  
        {
            this.Property2 = copy.Property2;
        }
    
        public Property2 { get; set; }
    
        public override object Clone()
        {
            return new SubClass(this);
        }
    
    }


    /Calle
    - Still confused, but on a higher level -
    • Proposed as answer by Louis.fr Saturday, February 27, 2010 4:36 PM
    • Marked as answer by Ji.Zhou Saturday, March 6, 2010 5:30 AM
    Friday, February 26, 2010 10:02 PM
  • Can't you just put a "new" before the method declaration to override it?

    -Romel Evans
    Saturday, February 27, 2010 7:01 AM
  • You can do like
    using System;
    using System.Threading;
    using System.Collections.Generic;
    
    class MainEntry
    {
        static void Main(string[] args)
        {
            ThisClass tc = new ThisClass() { Property1 = 1, Property2 = "2", Property3 = 3.0F, Property4 = "four" };
            object o = tc.Clone();
        }
        class Output : ICloneable
        {
            public object Property1 { set; get; }
            public object Property2 { set; get; }
            public object Property3 { set; get; }
    
            #region ICloneable Members
    
            public virtual object Clone()
            {
                return new Output() { Property1 = this.Property1, Property2 = this.Property2, Property3 = this.Property3 };
            }
    
            #endregion
        }
        class ThisClass : Output
        {
            public object Property4 { set; get; }
            public override object Clone()
            {
                Output op = base.Clone() as Output;
                return new ThisClass() { Property1 = op.Property1, Property2 = op.Property2, Property3 = op.Property3, Property4 = this.Property4 };
            }
        }
    }
    

    My Blog - MSDN Complement by providing Visual C# Walkthroughs and Sample Codes - Founded In February 24, 2010
    • Marked as answer by Ji.Zhou Saturday, March 6, 2010 5:29 AM
    Saturday, February 27, 2010 7:45 AM