Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloneable in Derived Classes

Tags:

c#

icloneable

Assume I have a class A, and B which derives from A:

class A : ICloneable
{
    public object Clone() {...}
}

class B : A, ICloneable
{
    public object Clone() {...}
}

which gives

'B.Clone()' hides inherited member 'A.Clone()'. Use the new keyword if hiding was intended.

warning.

(1) What is the suggested way? using new or declaring A.Clone() as virtual and override in B?

(2) If there are some members in A and properly cloned in A.Clone(), is there an easy way to clone them in B.Clone() or do I have to explicitly clone them in B.Clone() also?

like image 266
paul simmons Avatar asked Jan 15 '23 15:01

paul simmons


1 Answers

If you have access to your source (which I'm guessing is the case here) then absolutely declare it as virtual and override it. If hide the base Clone with new might be a bad idea. If any code doesn't know that it's working with a B, then it will fire the wrong clone method and not return a proper clone.

Regarding the assignment of properties, perhaps consider implementing copy constructors and each level can handle its own cloning:

    public class A : ICloneable
    {
        public int PropertyA { get; private set; }

        public A()
        {

        }

        protected A(A copy)
        {
            this.PropertyA = copy.PropertyA;
        }

        public virtual object Clone()
        {
            return new A(this);
        }
    }

    public class B : A, ICloneable
    {
        public int PropertyB { get; private set; }

        public B()
        {

        }

        protected B(B copy)
            : base(copy)
        {
            this.PropertyB = this.PropertyB;
        }

        public override object Clone()
        {
            return new B(this);
        }
    }

Each copy constructor calls the base copy constructor passing itself down the chain. Each inheritance level copies the properties belonging to it directly.

EDIT: If you use the new keyword to hide the base implementation, here's an example of what might happen. With a sample implementation (which on the face of it looks fine)

public class A : ICloneable
{
    public int PropertyA { get; protected set; }

    public object Clone()
    {
        Console.WriteLine("Clone A called");
        A copy = new A();
        copy.PropertyA = this.PropertyA;
        return copy;
    }
}

public class B : A, ICloneable
{
    public int PropertyB { get; protected set; }

    public new object Clone()
    {
        Console.WriteLine("Clone B called");
        B copy = new B();
        copy.PropertyA = this.PropertyA;
        copy.PropertyB = this.PropertyB;
        return copy;
    }
}

But when you use it:

B b = new B();
A a = b;
B bCopy = (B)a.Clone();
//"Clone A called" Throws InvalidCastException! We have an A!
like image 148
Chris Sinclair Avatar answered Jan 18 '23 23:01

Chris Sinclair