tags:

views:

182

answers:

4

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();

    return (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?

+1  A: 
Gacek
"nothing here" as in literally nothing. For now, I have inherited from the base type with the intention of adding new properties in the future
I see. I Edited my answer - please check new solution.
Gacek
@Gacek - Using the as keyword does not throw an exception but MyResult object is null although the CallFrameworkMethod returns a non null object.
Regarding your edit: if CallFrameworkMethod is returning a `Results` rather than a `MyResults` then your edit will just set `results` to null. The cast still fails, but the `as` operator indicates this by returning null rather than throwing an exception.
itowlson
@itowlson is right. Tested this approach.
Is there in the Results class a constructor, that allows to create one object basing on other? Something like `Results(Results referenceObject)`? If so, you can implement similar constructor in your class (by deriving the original constructor) and then call it like that: `var results = new MyResults(CallFrameworkMethod());`
Gacek
Unfortunately no. I looked at the Results implementation by the framework and it does not have this.
+4  A: 

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.

itowlson
Is this have to do with variance/covariance? I am on .NET 4.0 and i know that they did something for variance/covariance. Any idea?
No, C# 4.0 variance is to do with when you're using base/derived types as type parameters for generic interfaces or delegates; and you don't have any generic interfaces or delegates here. Your problem is more fundamental: it's about the concrete type of the object. A Results object simply *is not* an instance of the MyResults type. If CallFrameworkMethod returns an (actual) Results, references to that object *cannot* be cast to MyResults because the object *is not* a MyResults. The only way around this is to change CallFrameworkMethod to return a MyResults, or to create a new MyResults.
itowlson
variance won't help you here
Ben Voigt
A: 
Results results = new MyResults();
   ...

return (MyResults)results;

should work. If not, then the problem is somewhere alse.

Machta
No, because he then overwrites it with the return value of CallFrameworkMethod -- which is presumably returning something other than a MyResults, or the cast would succeed.
itowlson
CallFrameworkMethod() returns object of type Results
He makes an instance of the MyResult class and then calls the CallFrameworkMethod method which assigns to the results object some other instance which cannot be casted.
Machta
+1  A: 

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.

Ben Voigt
How would the copy constructor look? Can you give me some pointers?
C# doesn't have "copy constructors". But you can certainly write a reusable method that accepts the base class and returns an instance of the derived class, with all the base class members copied. Or were you asking about the generic idea?
Ben Voigt