Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Resolving Invalid Cast Exception Between an Inherited Class and Its Base

I have two classes, named Post and Question. Question is defined as:

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

My Question class does not override any members of Post, it just expresses a few other ones.


What I want to accomplish

I have an object of type Post, whose members are populated. Now, I want to convert it into a Question, so that I can add values for those few other members.

This is my current code, using an explicit cast conversion:

Post postToQuestion = new Post();

//Populate the Post...

Question ques = (Question)postToQuestion; //--> this is the error!

//Fill the other parts of the Question.

Problem

I am getting an InvalidCastException. What am I doing wrong?

like image 737
Maxim Zaslavsky Avatar asked Dec 13 '09 04:12

Maxim Zaslavsky


2 Answers

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

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

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

EDIT: Actually, I just tried typing up a demo for you doing 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 let you do implicit conversions with a base class.

like image 162
Joel Avatar answered Sep 24 '22 03:09

Joel


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

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

But even this is a code smell.

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

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

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

Question ques = (Question)post;

you'd have

Question ques = new Question(post);
like image 44
Dave Sims Avatar answered Sep 23 '22 03:09

Dave Sims