lomaxx
lomaxx

Reputation: 115823

Generic C# Copy Constructor

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?

Upvotes: 21

Views: 33072

Answers (5)

Nikita Ilin
Nikita Ilin

Reputation: 94

You may reference valueinjecter and fasterflect nuget packages and use:

public class Myclass()
{
    private string _property;
    public MyClass(MyClass obj)
    {
         this.InjectFrom(obj.DeepClone());
    }
}

Upvotes: 0

B2K
B2K

Reputation: 2611

Here's a constructor that I'm using. Note that this is a shallow constructor, and rather simplistic, due to the nature of my base class. Should be good enough to get you started.

public partial class LocationView : Location
{
    public LocationView() {}

    // base class copy constructor
    public LocationView(Location value) {
        Type t = typeof(Location);
        PropertyInfo[] properties = t.GetProperties();
        foreach (PropertyInfo pi in properties)
        {
            pi.SetValue(this, pi.GetValue(value, null), null);
        }
    }
    public Quote Quote { get; set; }
}

Upvotes: 11

Marc Gravell
Marc Gravell

Reputation: 1063338

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.

Upvotes: 17

Vordreller
Vordreller

Reputation: 2530

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.

Upvotes: 23

&#216;yvind Skaar
&#216;yvind Skaar

Reputation: 1840

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

Upvotes: 20

Related Questions