I am extending the existing .NET framework class by deriving it. How do I convert an object of base type to derived type?
public class Results { //Framework methods }
public class MyResults : Results { //Nothing here }
//I call the framework method
public static MyResults GetResults()
{
Results results = new Results();
//Results results = new MyResults(); //tried this as well.
results = CallFrameworkMethod();
retu开发者_Python百科rn (MyResults)results; //Throws runtime exception
}
I understand that this happens as I am trying to cast a base type to a derived type and if derived type has additional properties, then the memory is not allocated. When I do add the additional properties, I don't care if they are initialized to null.
How do I do this without doing a manual copy?
You can't. If results
doesn't refer to a MyResults
(e.g. if CallFrameworkMethod
returns a base Results
instance), then casting won't make it so: you'll need to create a new MyResults
, based on the existing non-MyResults
. Casting is about changing the compile-time type of the reference, not about changing the concrete type of the referenced object.
You can use tools such as Reflection or AutoMapper to help with the initialisation of the new MyResults
object -- but a new MyResults
object there must be, because you cannot tell a base Results
object to become a MyResults
object.
How about:
...
MyResults results = new MyResults();
...
And you maybe also need to create a COnstructor in your MyResults
class:
public class MyResults : Results
{
public MyResults() : base() {}
}
What exactly means "nothing here"?
EDIT
results = (CallFrameworkMethod() as MyResults);
It doesnt throw the exception, but if it would be useful for you - it depends on what you would like to do further...
No, you can't avoid copying the content into a instance of the derived type. Well, if you can change CallFrameworkMethod to be a generic method, and MyResults has a zero-argument constructor, then CallFrameworkMethod could create a new instance of your derived type directly, then use only the members of the parent type.
But probably you'll have to end up copying to a new object. Remember that this copying code can certainly be reused in another method, you don't have to rewrite it everywhere you need it.
As earlier answers have said, you need to instantiate a new instance of MyResults then copy the properties over from your Results object. You asked what a "copy constructor" was - it is just a constructor that takes an object and uses it to populate the object being constructed. For example:
public class Results
{
public string SampleProperty1 { get; set; }
public string SampleProperty2 { get; set; }
}
public class MyResults : Results
{
public MyResults(Results results)
{
SampleProperty1 = results.SampleProperty1;
SampleProperty2 = results.SampleProperty2;
}
}
A copy constructor is usually more convenient, readable and reusable than using code like this:
MyResults myResults = new MyResults
{
SampleProperty1 = results.SampleProperty1,
SampleProperty2 = results.SampleProperty2
};
If there are lots of properties and/or you are making lots of changes to the class you could use reflection (e.g. C# Using Reflection to copy base class properties ) or a tool such as AutoMapper ( http://automapper.codeplex.com ) to copy the properties. But often that can be overkill.
Results results = new MyResults();
...
return (MyResults)results;
should work. If not, then the problem is somewhere alse.
To downcast an Object into its derived class(es), The Object must be born in it derived class. For example: I have a simple class called Shape here is the code for Shape class
public class Shape{
public void draw(){}
}
and then I have an other class named Circle as follows:
public class Circle:Shape{
public void drawCircle(){}
}
Now if I create an object of Super class like
Shape noShape = new Shape();
And if try to downcast this noShape
object to Circle
object like this
Circle circle = (Circle) noShape;
it will generate an exception. This is because circle
was never born as Shape
To perform this down-casting functionality, noShape
must be born as Circle
object. Which can be done as this:
Circle initialShape = new Circle();
Now you can simply upcast this initialShape
object to Shape
object. like this
Shape upcastedObject = initialShape;
Now you can Down-cast the object upcastedObject
to its derived class like
Circle derivedCircle = (Circle) upcastedObject;
Now the derivedCircle
object will behave like a Circle
object. Because it was born as Circle
. I am using the word BORN so keep this in mind.
The reason of doing so or the use-case of doing so is up to your requirement.
精彩评论