Reputation: 115823
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
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
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
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
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
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