C#:解决继承类及其基类之间的无效转换异常

时间:2009-12-13 04:34:45

标签: c# .net oop inheritance casting

我有两个名为Post和Question的课程。问题定义为:

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

我的问题类不会覆盖Post的任何成员,它只是表达了一些其他成员。


我想要完成的事情

我有一个Post类型的对象,其成员已填充。现在,我想将其转换为一个问题,以便我可以为少数其他成员添加值。

这是我当前的代码,使用显式强制转换:

Post postToQuestion = new Post();

//Populate the Post...

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

//Fill the other parts of the Question.

问题

我收到了InvalidCastException。我做错了什么?

5 个答案:

答案 0 :(得分:22)

问题是你无法从父母转变为孩子。您可以为子类创建一个构造函数,将父类作为参数:     问题问题=新问题(myPost);

您还可以使用隐式运算符来简化此操作:     问题问题= myPost;

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

编辑: 实际上,我只是尝试为你做一个隐式运算符的演示:

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;
    }
}

但显然C#不允许你用基类进行隐式转换。

答案 1 :(得分:6)

此时发布不是问题,CLR正在抱怨。你可以将问题转发给Post,但不是反之亦然。现在,如果您对帖子的高级别引用是知道是一个问题,那么您可以像这样低估:

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

但即使这是a code smell

但我认为你想要实现的目标可以在没有类型转换的情况下实现,或者根本没有继承。遵循古老的"favor encapsulation over inheritance"原则,为什么不将Post对象包装到Question对象中,如下所示:

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

假设您已为Post的相关成员定义了属性,而不是

Question ques = (Question)post;

你有

Question ques = new Question(post);

答案 2 :(得分:4)

执行强制转换不会更改您正在投射的对象 - 因此无法将缺少的“问题”成员添加到“发布”对象中。我担心您只需要创建一个新的“问题”对象,并将您感兴趣的成员从“发布”复制到“问题”。

请注意,从“问题”到“发布”,以另一种方式进行投射可以正常工作,因为您可以将问题视为帖子而无需更改 - 所有必填字段都已存在。

答案 3 :(得分:3)

如果您想要更改类型,您需要编写代码,或者有时您可以序列化。转换不会更改类型(除非已编写自定义运算符)。

最简单的选项是首先将其创建为正确的类型:

Post post = new Question();

或者,添加转化运算符或其他方法,以便从帖子中创建Question

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

您还可以使用其他技巧,例如基于反射的属性副本或序列化;例如,使用MiscUtil

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

protobuf-net(需要一些额外的序列化属性):

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

答案 4 :(得分:0)

你可以这样做:

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
    }
}

...如果你从数据存储区实例化Post?