views:

3611

answers:

3

What would be the best way to write a generic copy constructor function for my c# classes? They all inherit from an abstract base class so I could use reflection to map the properties, but I'm wondering if there's a better way?

+9  A: 

Avoid reflection if you can. Each class should have the responsibility of copying its own properties, and send it further to the base method.

Øyvind Skaar
so just to clarify, it'd be best if you had a custom copy constructor on each class that explicitly mapped the properties?
lomaxx
I would. How hard is it to write? Certainly easier to read at a glance than a reflection-based method.
duffymo
Yes, I would recommend that approach.
Øyvind Skaar
It's not hard to read and it's certainly easy to write, however there are maintenance issues to consider. If you add a new property to the class you need to update the copy constructor and tests which is pretty easy to forget.
lomaxx
I would disagree about updating the copy constructor. And depending on what the new property changed I'm not sure that you'd need to do more than just re-run your existing tests. Adding another get/set pair doesn't require new unit tests for each.
duffymo
how would you copy the newly added properties if you don't update the copy constructor?
lomaxx
+8  A: 

A copy constructor basically means you have a single parameter, which is the object you're going to copy.

Also, do a deep copy, not a shallow copy.

If you don't know what deep and shallow copies are, then here's the deal:

Suppose you're copying a class that has a single row of integers as field.

A shallow copy would be:

public class Myclass()
{
    private int[] row;
    public MyClass(MyClass class)
    {
        this.row = class.row
    }
}

deep copy is:

public class Myclass()
{
    private int[] row;
    public MyClass(MyClass class)
    {
        for(int i = 0; i<class.row.Length;i++)
        {
            this.row[i] = class.row[i];
        }
    }
}

A deep copy really gets the actuall values and puts them in a new field of the new object, whilst a shallow copy only copies the pointers.

With the shallow copy, if you set:

row[3] = 5;

And then print both rows, both prints will have 5 as value of the 4th number. With a deep copy however, only the first print will have this, since the rows don't have the same pointers.

Vordreller
+2  A: 

You can create a shallow copy efficiently with reflection by pre-compiling it, for example with Expression. For example, like so.

For deep copies, serialization is the most reliable approach.

Marc Gravell