views:

383

answers:

1

Coming from a C++ background, I am finding cloning of objects in C# a little hard to get used to. To clear up some of my confusion, I am looking for an elegant way to clone an object of a base type to a derived type.

To illustrate:

public class Base
{
    public string Member1;
    public int Member2;
    public float Member3;
    public bool Member4;
}

public class Derived : Base
{
    public List<Base> Children;
}

Base base = new Base();

And with that I want to create an instance of "Derived" whilst doing a memberwise copy of the Base object - preferably without assigning them manually.

Note: Maybe this would be more suited to a value type?

+3  A: 

Since you can't change the type of an object, you have a few options:

  • encapsulate Base
  • use a constructor that copies the values from Base
  • copy the properties from Base through reflection or similar

For the latter, MiscUtil has a helpful tool:

Base b= ...
Derived item = PropertyCopy<Derived>.CopyFrom(b);

For encapsulation:

public class Derived
{
    readonly Base b;
    public Derived(Base b) {this.b=b;}
    public List<Base> Children;
    public string Member1 {get {return b.Member1;} set {...} }
    public int Member2 {etc}
    public float Member3 {etc}
    public bool Member4 {etc}
}

Or as a manual copy:

public class Derived : Base
{
    public Derived(Base b) {
        this.Member1 = b.Member1;
        // etc
    }
    // additional members...
}

or (comments) get the base to copy itself:

public class Derived : Base
{
    public Derived(Base b) : base(b) { }
    // additional members...
}
public class Base
{
    // members not shown...
    public Base() {}
    protected Base(Base b) {
       this.Member1 = b.Member1;
        // etc
    }
    // additional members...
}

(where Base's constructor initializes the fields from Base)

Marc Gravell
You can improve the "manual copy" version by using copy constructors - this way you can ask `Base` to create a copy of itself, and it can play with its privates as well, if needed - it also works if there is more than one derived class from it.
Rowland Shaw
True; updated
Marc Gravell
MiscUtil is exactly what I need, thanks.
Nat Ryall