[ACCEPTED]-C#: Resolving Invalid Cast Exception Between an Inherited Class and Its Base-casting

Accepted answer
Score: 23

The problem is that you can't cast from 10 parent to child. You can create a constructor 9 for the child class that takes the parent 8 class as a param: Question ques = new 7 Question(myPost);

You could also use the 6 implicit operator to make it simple to do 5 this: Question ques = myPost;

http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx

EDIT: Actually, I 4 just tried typing up a demo for you doing 3 the implicit operator:

class Question : Post
{
    public Question()
    {
        //...
    }

    public Question(Post p)
    {
        // copy stuff to 'this'
    }

    public static implicit operator Question(Post p)
    {
        Question q = new Question(p);
        return q;
    }
}

but aparently C# doesn't 2 let you do implicit conversions with a base 1 class.

Score: 6

Post is not a Question at this point and 13 the CLR is rightly complaining. You could 12 upcast Question to Post but not visa-versa. Now, if 11 you had a high-level reference to a Post 10 that you knew was a Question, you could downcast 9 like this:

public Post Post 
{
    set
    {
        if (value is Question)
        {
            question = (Question)value;
        }
    }
}

But even this is a code smell.

But I think 8 what you're trying to accomplish can be 7 achieved without class casting, or maybe 6 without inheritance at all. Following the 5 venerable "favor encapsulation over inheritance" principle, why not just wrap 4 the Post object into your Question object 3 with something like:

public class Question 
{
    Post post;
    public Question(Post post)
    {
        this.post = post;
    }
}

Assuming you've defined 2 properties for Post's relevant members, instead 1 of

Question ques = (Question)post;

you'd have

Question ques = new Question(post);
Score: 4

Doing a cast doesn't change the object you 10 are casting - so it can't add the missing 9 'Question' members to your 'Post' object. I'm 8 afraid you're just going to have to create 7 a new 'Question' object, and copy the members 6 you're interested in from 'Post' to 'Question'.

Note 5 that doing the cast the other way, from 4 'Question' to 'Post', would work fine, because 3 you can treat a Question like a Post without 2 having to change it - all the required fields 1 are already there.

Score: 3

If you want to change the type, you need to either 10 write code, or sometimes you can serialize. Casting 9 doesn't change the type (unless a custom 8 operator has been written).

The simplest option is 7 to create it as the right type in the first 6 place:

Post post = new Question();

Alternatively, add a conversion operator 5 or some other method for creating a Question from 4 a post:

class Question {
    public Question(Post post) {
        this.Author = post.Author;
        this.Body = post.Body;
        // ...
    }
}
...
Question question = new Question(post);

You can also use other tricks, like 3 reflection-based property copies, or serialization; for 2 example, using MiscUtil:

Question question = PropertyCopy<Question>.CopyFrom(post);

or protobuf-net (requires some extra 1 serialization attributes):

Question question = Serializer.ChangeType<Post,Question>(post);
Score: 0

Could you do this:

public Question(Post P) : base(p) {...}

class Post 
{
    public Post(Post P)
    {
         populate(P.ID);
    }

    void populate(int ID)
    {
         // load from DB, or however it happens
    }
}

...If you instantiate 1 Post from a datastore anyway?

More Related questions