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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1895552/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 21:42:07  来源:igfitidea点击:

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

c#.netoopinheritancecasting

提问by Maxim Zaslavsky

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

我有两个类,名为 Post 和 Question。问题定义为:

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

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

我的 Question 类不会覆盖 Post 的任何成员,它只是表示其他一些成员。



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.

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

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?

我收到一个 InvalidCastException。我究竟做错了什么?

采纳答案by Joel

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

问题是你不能从父级转换到子级。您可以为子类创建一个以父类为参数的构造函数: Question ques = new Question(myPost);

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

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

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

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.

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

回答by Bruce

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

进行转换不会更改您正在转换的对象 - 因此它无法将缺少的“问题”成员添加到您的“发布”对象中。恐怕您只需要创建一个新的“问题”对象,然后将您感兴趣的成员从“发布”复制到“问题”。

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

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

回答by Dave Sims

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 knewwas a Question, you could downcast like this:

在这一点上,发布不是问题,CLR 的抱怨是正确的。您可以将 Question 上传到 Post,但反之则不然。现在,如果你有一个对你知道是一个问题的帖子的高级引用,你可以像这样沮丧:

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:

但我认为你想要完成的事情可以在没有类转换的情况下实现,或者根本没有继承。遵循古老的“优先封装而不是继承”原则,为什么不将 Post 对象包装到您的 Question 对象中,例如:

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

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

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

Question ques = (Question)post;

you'd have

你会有

Question ques = new Question(post);

回答by Marc Gravell

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

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

The simplestoption is to create it as the right type in the first place:

最简单的方法是将其创建为在第一时间正确的类型:

Post post = new Question();

Alternatively, add a conversion operator or some other method for creating a Questionfrom a post:

或者,添加一个转换运算符或其他一些方法来Question从帖子创建一个:

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 reflection-based property copies, or serialization; for example, using MiscUtil:

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

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

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

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

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

回答by Steve Syfuhs

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 Post from a datastore anyway?

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