Convert base class to derived class
Solution 1
No, there's no built-in way to convert a class like you say. The simplest way to do this would be to do what you suggested: create a DerivedClass(BaseClass)
constructor. Other options would basically come out to automate the copying of properties from the base to the derived instance, e.g. using reflection.
The code you posted using as
will compile, as I'm sure you've seen, but will throw a null reference exception when you run it, because myBaseObject as DerivedClass
will evaluate to null
, since it's not an instance of DerivedClass
.
Solution 2
That's not possible. but you can use an Object Mapper like AutoMapper
EDIT
I want to suggest a simpler object mapper: TinyMapper. AutoMapper is now very complicated to use. I don't use it anymore. TinyMapper covers most use cases and is far more simple AND super fast.
Example:
//In app startup
TinyMapper.Bind<Person, PersonDto>();
//Usage
var personDto = TinyMapper.Map<PersonDto>(person);
Example for AutoMapper (older versions I think) for the ones who still want to use it:
class A
{
public int IntProp { get; set; }
}
class B
{
public int IntProp { get; set; }
public string StrProp { get; set; }
}
In global.asax or application startup:
AutoMapper.Mapper.CreateMap<A, B>();
Usage:
var b = AutoMapper.Mapper.Map<B>(a);
It's configurable via a fluent API.
Solution 3
I have found one solution to this, not saying it's the best one, but it feels clean to me and doesn't require any major changes to my code. My code looked similar to yours until I realized it didn't work.
My Base Class
public class MyBaseClass
{
public string BaseProperty1 { get; set; }
public string BaseProperty2 { get; set; }
public string BaseProperty3 { get; set; }
public string BaseProperty4 { get; set; }
public string BaseProperty5 { get; set; }
}
My Derived Class
public class MyDerivedClass : MyBaseClass
{
public string DerivedProperty1 { get; set; }
public string DerivedProperty2 { get; set; }
public string DerivedProperty3 { get; set; }
}
Previous method to get a populated base class
public MyBaseClass GetPopulatedBaseClass()
{
var myBaseClass = new MyBaseClass();
myBaseClass.BaseProperty1 = "Something"
myBaseClass.BaseProperty2 = "Something else"
myBaseClass.BaseProperty3 = "Something more"
//etc...
return myBaseClass;
}
Before I was trying this, which gave me a unable to cast error
public MyDerivedClass GetPopulatedDerivedClass()
{
var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass();
newDerivedClass.UniqueProperty1 = "Some One";
newDerivedClass.UniqueProperty2 = "Some Thing";
newDerivedClass.UniqueProperty3 = "Some Thing Else";
return newDerivedClass;
}
I changed my code as follows bellow and it seems to work and makes more sense now:
Old
public MyBaseClass GetPopulatedBaseClass()
{
var myBaseClass = new MyBaseClass();
myBaseClass.BaseProperty1 = "Something"
myBaseClass.BaseProperty2 = "Something else"
myBaseClass.BaseProperty3 = "Something more"
//etc...
return myBaseClass;
}
New
public void FillBaseClass(MyBaseClass myBaseClass)
{
myBaseClass.BaseProperty1 = "Something"
myBaseClass.BaseProperty2 = "Something else"
myBaseClass.BaseProperty3 = "Something more"
//etc...
}
Old
public MyDerivedClass GetPopulatedDerivedClass()
{
var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass();
newDerivedClass.UniqueProperty1 = "Some One";
newDerivedClass.UniqueProperty2 = "Some Thing";
newDerivedClass.UniqueProperty3 = "Some Thing Else";
return newDerivedClass;
}
New
public MyDerivedClass GetPopulatedDerivedClass()
{
var newDerivedClass = new MyDerivedClass();
FillBaseClass(newDerivedClass);
newDerivedClass.UniqueProperty1 = "Some One";
newDerivedClass.UniqueProperty2 = "Some Thing";
newDerivedClass.UniqueProperty3 = "Some Thing Else";
return newDerivedClass;
}
Solution 4
You can implement the conversion yourself, but I would not recommend that. Take a look at the Decorator Pattern if you want to do this in order to extend the functionality of an existing object.
Solution 5
No, there is no built in conversion for this. You'll need to create a constructor, like you mentioned, or some other conversion method.
Also, since BaseClass is not a DerivedClass, myDerivedObject will be null, andd the last line above will throw a null ref exception.
ARW
Updated on June 16, 2021Comments
-
ARW about 3 years
Is it possible in C# to explicitly convert a base class object to one of it's derived classes? Currently thinking I have to create a constructor for my derived classes that accept a base class object as a parameter and copy over the property values. I don't really like this idea, so I'd like to avoid it if possible.
This doesn't seem like it should work (object is instantiated as new base, so memory shouldn't be allocated for extra members of the derived class) but C# seems to allow me to do it:
class BaseClass { ... some stuff ... } class DerivedClass : BaseClass { public bool MyDerivedProperty{ get; set; } } static void Main(string[] args) { BaseClass myBaseObject = new BaseClass(); DerivedClass myDerivedObject = myBaseObject as DerivedClass; myDerivedObject.MyDerivedProperty = true; }
-
Erix almost 12 yearsYou're going to get a null ref exception on the last line.
-
Paul Aldred-Bann almost 12 yearsAlready answered here: stackoverflow.com/questions/729527/…
-
Seng Cheong almost 12 yearsYou should read about when it is appropriate to use "as" vs. a regular cast. If you use a cast here, C# compiler will tell you that what you're doing is wrong.
-
Sam I am says Reinstate Monica about 10 yearsI've voted to reopen because the marked "duplicate" is a completely different question. This question is about conversion, and the "duplicated" question is about casting
-
Jesse de gans about 5 yearsThe best and fastes option is to use JsonConvert you can find my answer on the original question
-
-
Bruno Casali almost 10 yearsVery good! exactly I want! thx :D
-
A Khudairy over 9 yearseach time you add a property you will have to edit this. so for others readin this I suggest you think of using composition instead
-
Ahmed Alejo about 8 yearsthis throws a NullReferenceException, so doesn´t work as stated
-
Haroen Viaene almost 8 yearsthanks for this, the other answers didn't say how to cast
-
peter70 about 7 yearsSometimes, a little bit of rethinking, can save from major problems. Thank you!
-
Bassie about 6 yearsbut this doesn't work (as ahmed mentioned it throws null reference exception)
-
Papa Ccompis almost 6 yearsThis concept helped me solve an issue in my project. In my case, I didn't use the syntax "as DerivedClass". Instead, I cast the object like this DerivedClass myDerivedObject = (DerivedClass) myBaseObject; That worked for me.
-
HeonAle about 5 yearsThis works great but you have to initialize it first AutoMapper.Mapper.Initialize(cfg => cfg.CreateMap<A, B>());
-
Alex Klaus almost 5 yearsRefer to the official AutoMapper Usage Guidelines published in 2019 for the DOs and DONTs in
AutoMapper
-
Tomasz Chudzik over 4 yearsStarting from version 9.0 of the AutoMapper static API is no longer supported. You will need to do something like this: var configuration = new MapperConfiguration(cfg => { cfg.CreateMap<A, B>(); }); var mapper = new Mapper(configuration); var b = mapper.Map<A, B>(a); Then it is a good idea to store you configuration or mapper in your dependency container.
-
Newclique over 4 yearsThis is excellent info. I'll add this as a tangent: I was looking for a way to use AutoMapper v 9.0+ in MVC. I ended up making a static property in Global.asax.cs and assigning the configured mapper to it during Application_Start. Hope that helps someone who maybe didn't think about this approach. In .net Core you could just have the mapper injected into your controller instances but this isn't available in the "traditional" .net framework.
-
nivs1978 over 4 yearsVoodo like Automapper should generally be avoided. It uses reflection to run trough properties and is in general expensive to use, compared to other solution (like writing a.prop1=b.pro1, a.pro2=b.prop2 etc.)
-
AnthonyVO over 3 yearsThere is no conversion happening here. The base class pointer (myBaseObject) was simply set to an instance of a DerivedClass. It remains a DerivedClass from start to finish.