Best way to create instance of child object from parent object
Solution 1
The base class needs to define a copy constructor:
public class MyObject
{
protected MyObject(MyObject other)
{
this.Prop1=other.Prop1;
this.Prop2=other.Prop2;
}
public object Prop1 { get; set; }
public object Prop2 { get; set; }
}
public class MyObjectSearch : MyObject
{
public double Distance { get; set; }
public MyObjectSearch(MyObject obj)
: base(obj)
{
this.Distance=0;
}
public MyObjectSearch(MyObjectSearch other)
: base(other)
{
this.Distance=other.Distance;
}
}
This way the setting of properties is handled for all derived classes by the base class.
Solution 2
You can use reflection to copy properties.
public class ChildClass : ParentClass
{
public ChildClass(ParentClass ch)
{
foreach (var prop in ch.GetType().GetProperties())
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(ch, null), null);
}
}
}
Solution 3
There is no easy way to do this, unfortunately. As you said, you would either have to use reflection, or create a "Clone" method that would generate a new child object using a parent object as input, like so:
public class MyObjectSearch : MyObject {
// Other code
public static MyObjectSearch CloneFromMyObject(MyObject obj)
{
var newObj = new MyObjectSearch();
// Copy properties here
obj.Prop1 = newObj.Prop1;
return newObj;
}
}
No matter what, you're either going to end up writing reflection code (which is slow), or writing each property out by hand. It all depends on whether or not you want maintainability (reflection) or speed (manual property copy).
Solution 4
A generic solution would be to serialize it to json and back. In the json-string is no information about the class name from which it was serialized. Most people do this in javascript.
As you see it works well for pocco objects but i don't guarantee that it works in every complex case. But it does event for not-inherited classes when the properties are matched.
using Newtonsoft.Json;
namespace CastParentToChild
{
public class Program
{
public static void Main(string[] args)
{
var p = new parent();
p.a=111;
var s = JsonConvert.SerializeObject(p);
var c1 = JsonConvert.DeserializeObject<child1>(s);
var c2 = JsonConvert.DeserializeObject<child2>(s);
var foreigner = JsonConvert.DeserializeObject<NoFamily>(s);
bool allWorks = p.a == c1.a && p.a == c2.a && p.a == foreigner.a;
//Your code goes here
Console.WriteLine("Is convertable: "+allWorks + c2.b);
}
}
public class parent{
public int a;
}
public class child1 : parent{
public int b=12345;
}
public class child2 : child1{
}
public class NoFamily{
public int a;
public int b = 99999;
}
// Is not Deserializeable because
// Error 'NoFamily2' does not contain a definition for 'a' and no extension method 'a' accepting a first argument of type 'NoFamily2' could be found (are you missing a using directive or an assembly reference?)
public class NoFamily2{
public int b;
}
}
Solution 5
If a shallow copy is enough, you can use the MemberwiseClone
method.
Example:
MyObject shallowClone = (MyObject)original.MemberwiseClone();
If you need a deep copy, you can serialize/deserialize like this: https://stackoverflow.com/a/78612/1105687
An example (assuming you write an extension method as suggested in that answer, and you call it DeepClone)
MyObject deepClone = original.DeepClone();
Captain John
UK Based software developer. Mainly working with .NET, Azure, Javascript and SQL
Updated on June 08, 2021Comments
-
Captain John almost 3 years
I'm creating a child object from a parent object. So the scenario is that I have an object and a child object which adds a distance property for scenarios where I want to search. I've chosen to use inheritance as my UI works equivalently with either a search object or a list of objects not the result of a location search. So in this case inheritance seems a sensible choice.
As present I need to generate a new object
MyObjectSearch
from an instance ofMyObject
. At present I'm doing this in the constructor manually by setting properties one by one. I could use reflection but this would be slow. Is there a better way of achieving this kind of object enhancement?Hopefully my code below illustrates the scenario.
public class MyObject { // Some properties and a location. } public class MyObjectSearch : MyObject { public double Distance { get; set; } public MyObjectSearch(MyObject obj) { base.Prop1 = obj.Prop1; base.Prop2 = obj.Prop2; } }
And my search function:
public List<MyObjectSearch> DoSearch(Location loc) { var myObjectSearchList = new List<MyObjectSearch>(); foreach (var object in myObjectList) { var distance = getDistance(); var myObjectSearch = new MyObjectSearch(object); myObjectSearch.Distance = distance; myObjectSearchList.add(myObjectSearch); } return myObjectSearchList; }
-
Patrick Hofman over 10 yearsI think this is a good solution, since it is a better safeguard for passing all parameters then the copy or clone methods. When you really want to be sure, use reflection or similar solutions (like serializing properties from and to, but that might be too much)
-
John Alexiou over 10 yearsI do not see why have all the properties as arguments when a reference to the base class would suffice. You want
MyObject
to handle copying itself as good programming practices. -
BartoszKP over 10 years@ja72 Just an example - such constructor is a typical general-purpose constructor. Depending on particular usage of the class, your solution or others proposed in other answers might be suitable.
-
Patrick Hofman over 10 yearsI agree with Bartosz. When implementing it like this, you cannot add a property in the constructor without an error in the parent class. This reminds you to add the field to the parent class.
-
rolivares about 10 yearsI think this is the best approach, there is no possibility to do this by cloning the source object. It's a really pain.
-
corentinaltepe over 7 yearsThis is very clean and fixes my issues with deep copy and inheritance.
-
CarComp about 5 yearsSometimes google shows you what you really wanted to know, regardless of what you asked.
-
Nitin Sawant almost 2 yearsthis is good way but need to write code for copying all the property values
-
John Alexiou almost 2 years@NitinS - yes you need to write code to do the copying per the requirements of the project. In some cases you need a shallow copy and others a deep copy. It is up to you, and this is what it is not automated. For an automatic solution look into
record
definitions which are classes that behave likestruct
.